feat: add colored active state to status filter pills
All checks were successful
Build & Publish / publish (push) Successful in 43s
All checks were successful
Build & Publish / publish (push) Successful in 43s
FilterPill gains activeColor prop — when active, border/text/background tint match the status color instead of generic amber. Inactive dots are muted at 40% opacity for clear active/inactive contrast. Applied to TopBar status pills and EventFeed severity pills. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,13 @@ const DEFAULT_ICONS: Record<SeverityFilter, string> = {
|
|||||||
running: '\u2699', // ⚙
|
running: '\u2699', // ⚙
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SEVERITY_COLORS: Record<SeverityFilter, string> = {
|
||||||
|
error: 'var(--error)',
|
||||||
|
warning: 'var(--warning)',
|
||||||
|
success: 'var(--success)',
|
||||||
|
running: 'var(--running)',
|
||||||
|
}
|
||||||
|
|
||||||
const SEVERITY_LABELS: Record<SeverityFilter, string> = {
|
const SEVERITY_LABELS: Record<SeverityFilter, string> = {
|
||||||
error: 'Error',
|
error: 'Error',
|
||||||
warning: 'Warning',
|
warning: 'Warning',
|
||||||
@@ -140,6 +147,9 @@ export function EventFeed({ events, maxItems = 200, className }: EventFeedProps)
|
|||||||
key={sev}
|
key={sev}
|
||||||
label={SEVERITY_LABELS[sev]}
|
label={SEVERITY_LABELS[sev]}
|
||||||
count={count}
|
count={count}
|
||||||
|
dot
|
||||||
|
dotColor={SEVERITY_COLORS[sev]}
|
||||||
|
activeColor={SEVERITY_COLORS[sev]}
|
||||||
active={activeFilters.has(sev)}
|
active={activeFilters.has(sev)}
|
||||||
onClick={() => toggleFilter(sev)}
|
onClick={() => toggleFilter(sev)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ interface TopBarProps {
|
|||||||
className?: string
|
className?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const STATUS_PILLS: { status: ExchangeStatus; label: string }[] = [
|
const STATUS_PILLS: { status: ExchangeStatus; label: string; color: string }[] = [
|
||||||
{ status: 'completed', label: 'OK' },
|
{ status: 'completed', label: 'OK', color: 'var(--success)' },
|
||||||
{ status: 'warning', label: 'Warn' },
|
{ status: 'warning', label: 'Warn', color: 'var(--warning)' },
|
||||||
{ status: 'failed', label: 'Error' },
|
{ status: 'failed', label: 'Error', color: 'var(--error)' },
|
||||||
{ status: 'running', label: 'Running' },
|
{ status: 'running', label: 'Running', color: 'var(--running)' },
|
||||||
]
|
]
|
||||||
|
|
||||||
export function TopBar({
|
export function TopBar({
|
||||||
@@ -58,10 +58,13 @@ export function TopBar({
|
|||||||
|
|
||||||
{/* Status pills */}
|
{/* Status pills */}
|
||||||
<div className={styles.filters}>
|
<div className={styles.filters}>
|
||||||
{STATUS_PILLS.map(({ status, label }) => (
|
{STATUS_PILLS.map(({ status, label, color }) => (
|
||||||
<FilterPill
|
<FilterPill
|
||||||
key={status}
|
key={status}
|
||||||
label={label}
|
label={label}
|
||||||
|
dot
|
||||||
|
dotColor={color}
|
||||||
|
activeColor={color}
|
||||||
active={globalFilters.statusFilters.has(status)}
|
active={globalFilters.statusFilters.has(status)}
|
||||||
onClick={() => globalFilters.toggleStatus(status)}
|
onClick={() => globalFilters.toggleStatus(status)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -35,6 +35,14 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dotMuted {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeColored {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ interface FilterPillProps {
|
|||||||
active?: boolean
|
active?: boolean
|
||||||
dot?: boolean
|
dot?: boolean
|
||||||
dotColor?: string
|
dotColor?: string
|
||||||
|
activeColor?: string
|
||||||
onClick?: () => void
|
onClick?: () => void
|
||||||
className?: string
|
className?: string
|
||||||
}
|
}
|
||||||
@@ -18,21 +19,27 @@ export const FilterPill = forwardRef<HTMLButtonElement, FilterPillProps>(
|
|||||||
active = false,
|
active = false,
|
||||||
dot = false,
|
dot = false,
|
||||||
dotColor,
|
dotColor,
|
||||||
|
activeColor,
|
||||||
onClick,
|
onClick,
|
||||||
className,
|
className,
|
||||||
}, ref) => {
|
}, ref) => {
|
||||||
const classes = [
|
const classes = [
|
||||||
styles.pill,
|
styles.pill,
|
||||||
active ? styles.active : '',
|
active ? styles.active : '',
|
||||||
|
active && activeColor ? styles.activeColored : '',
|
||||||
className ?? '',
|
className ?? '',
|
||||||
].filter(Boolean).join(' ')
|
].filter(Boolean).join(' ')
|
||||||
|
|
||||||
|
const activeStyle = active && activeColor
|
||||||
|
? { borderColor: activeColor, backgroundColor: `color-mix(in srgb, ${activeColor} 12%, transparent)`, color: activeColor } as React.CSSProperties
|
||||||
|
: undefined
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button ref={ref} className={classes} onClick={onClick} type="button" data-active={active || undefined}>
|
<button ref={ref} className={classes} style={activeStyle} onClick={onClick} type="button" data-active={active || undefined}>
|
||||||
{dot && (
|
{dot && (
|
||||||
<span
|
<span
|
||||||
className={styles.dot}
|
className={`${styles.dot} ${!active ? styles.dotMuted : ''}`}
|
||||||
style={dotColor ? { background: dotColor } : undefined}
|
style={dotColor ? { background: active ? dotColor : undefined } : undefined}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<span className={styles.label}>{label}</span>
|
<span className={styles.label}>{label}</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user