feat(ui): add breadcrumb icons, fix alignment, and remove duplicate form headers

- add section icons to all breadcrumbs across every page
- fix breadcrumb nav display:flex so icons align vertically with buttons
- wrap all page breadcrumbs in pageToolbar div for consistent layout
- add Breadcrumbs to AllRunsPage which previously used a plain h1
- fix envCardHeader flex:1 so settings button hugs the right edge
- remove card header from environment create/edit forms (duplicated breadcrumb)
This commit is contained in:
2026-04-10 19:58:33 +03:00
parent de0cbeef7c
commit 99da7ac891
37 changed files with 224 additions and 84 deletions
@@ -45,6 +45,25 @@
}
}
/* ── Clickable / hover ────────────────────────────────────── */
.clickable {
cursor: pointer;
border-radius: 99px;
padding: 2px 6px;
margin: -2px -6px;
transition: background var(--transition);
}
.clickable:hover {
background: color-mix(in srgb, var(--color-text) 8%, transparent);
}
.clickable:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* ── Active state ─────────────────────────────────────────── */
.active .dot::before {
@@ -67,3 +86,18 @@
color: var(--color-text-muted);
opacity: 0.5;
}
/* ── Error state ──────────────────────────────────────────── */
.error .dot::before {
background: var(--color-error-fg);
}
.error .ring {
animation: none;
}
.error .label {
color: var(--color-error-fg);
font-weight: 600;
}
@@ -4,24 +4,39 @@ export interface AutoRefreshIndicatorProps {
active: boolean;
pulseKey?: number;
label?: string;
error?: boolean;
onClick?: () => void;
}
export function AutoRefreshIndicator({
active,
pulseKey,
label = 'Live',
error = false,
onClick,
}: AutoRefreshIndicatorProps) {
const stateClass = error ? styles.error : active ? styles.active : styles.inactive;
const titleText = error
? 'Refresh failed — click to retry'
: active
? 'Auto-refreshing'
: 'Auto-refresh stopped';
return (
<div
className={[styles.root, active ? styles.active : styles.inactive].join(' ')}
title={active ? 'Auto-refreshing' : 'Auto-refresh stopped'}
aria-label={active ? 'Auto-refreshing' : 'Auto-refresh stopped'}
className={[styles.root, stateClass, onClick ? styles.clickable : ''].join(' ')}
title={titleText}
aria-label={titleText}
aria-live="polite"
role={onClick ? 'button' : undefined}
tabIndex={onClick ? 0 : undefined}
onClick={onClick}
onKeyDown={onClick ? (e) => (e.key === 'Enter' || e.key === ' ') && onClick() : undefined}
>
<span className={styles.dot}>
{pulseKey !== undefined && pulseKey > 0 && <span key={pulseKey} className={styles.ring} />}
</span>
<span className={styles.label}>{label}</span>
<span className={styles.label}>{error ? 'Error' : label}</span>
</div>
);
}