Filter Pills
Active filters rendered as removable chips. Each chip shows "label: displayValue" and an x button that dispatches a bubbling esa-filter-remove event carrying { name, value }.
Preview
Pass the current active filters; each becomes a removable chip.
<FilterPills filters={[
{ name: 'status', label: 'Status', value: 'open', displayValue: 'Open' },
{ name: 'status', label: 'Status', value: 'review', displayValue: 'In review' },
{ name: 'dept', label: 'Department', value: 'water', displayValue: 'Water Quality' },
]} /> States
A single chip renders inline; with no filters the component renders nothing at all — matching the Angular @if (activeFilters().length > 0) guard.
<FilterPills filters={[
{ name: 'priority', label: 'Priority', value: 'high', displayValue: 'High' },
]} />
<!-- Empty: renders no DOM -->
<FilterPills filters={[]} /> API
| Prop | Type | Default | Description |
|---|---|---|---|
filters | ActiveFilter[] | [] | Active filters to render. Each is { name, label, value, displayValue }. Empty renders no DOM. |
Events
| Prop | Type | Default | Description |
|---|---|---|---|
esa-filter-remove | { name, value } | — | Bubbling/composed. Fires when a chip's remove button is clicked, identifying which filter to drop. |
Accessibility
- Each chip carries an
aria-labelof "label: displayValue" so the pairing is announced as one unit. - Remove buttons are native
<button>s with an explicit "Remove {label} {displayValue}" accessible name. - Remove buttons show a visible focus ring via
--focus-ring-*tokens.
Theming surface
Every public token this component reads, extracted from its source at build time.
The Resolves to column walks each token's real lineage —
component → semantic → primitive → raw value — so you
can see exactly where re-pointing it lands. A spoke re-skins by overriding these in
its theme-<slug>.css; component internals are never edited. No
hook for what you need? File it with /request-lego.
| Token | Tier | Resolves to |
|---|---|---|
--filter-pill-bg | component | #e9f6e9 via --color-primary-bg → --color-grass-3 |
--filter-pill-bg-hover | component | #daf1db via --color-primary-bg-hover → --color-grass-4 |
--filter-pill-font-size | component | clamp(0.625rem, 0.56rem + 0.32vw, 0.75rem) via --type-size-100 |
--filter-pill-label-color | component | #646464 via --color-text-secondary → --color-gray-11 |
--filter-pill-radius | component | 9999px via --radius-full |
--filter-pill-remove-color | component | #646464 via --color-text-secondary → --color-gray-11 |
--filter-pill-remove-color-hover | component | #ce2c31 via --color-danger-strong → --color-red-11 |
--filter-pill-text | component | #2a7e3b via --color-primary-strong → --color-grass-11 |
--focus-ring-color | component | #65ba74 via --color-border-focus → --color-grass-8 |
--focus-ring-width | component | 2px |
--font-sans | semantic | 'DM Sans', sans-serif |
--transition-fast | semantic | 150ms ease |
--font-weight-medium | primitive | 500 |
--radius-full | primitive | 9999px |
--spacing-050 | primitive | 0.125rem |
--spacing-100 | primitive | 0.25rem |
--spacing-200 | primitive | 0.5rem |
--spacing-300 | primitive | 0.75rem |