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,
split by blast radius: the hooks that belong to this component,
then the shared and system tokens it consumes alongside everything else. 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.
Type roles it names
This component does not set a size, weight, face or tracking of its own — it names a composite, and the composite carries all five. A composite is a class rather than a token, so none of it appears in the tables below; re-theme text by re-pointing the token family, not by editing the component.
| Role | Re-point | Reach |
|---|---|---|
.typography-microcopy-xs |
| +6 more componentsesa-app-shell, esa-button, esa-button-toggle, esa-kbd, esa-pill, esa-range-slider |
.typography-microcopy-xs-subtle |
| +7 more componentsesa-combobox, esa-date-picker, esa-filter-dropdown, esa-input-tag, esa-select, esa-text-field, esa-tooltip |
Wired to this component
None. This component has no hooks of its own — it themes entirely through the shared tokens below, so every override here also moves its siblings.
Shared tokens it reads
Owned by a family or by the semantic layer. Still overridable — but scope the
override (esa-foo { --form-border-color: … }) unless you mean to move
everything that reads it. Reach says what else that is.
| Token | Reach | Resolves to |
|---|---|---|
--focus-ring-color | component focus ring group · +34 more | #3e9b4f via --color-border-default-focus → --color-grass-10 |
--focus-ring-width | component focus ring group · +35 more | 2px via --border-width-focus → --border-width-200 |
--color-background-brand-muted | semantic every component | #e9f6e9 via --color-grass-3 |
--color-background-brand-muted-hover | semantic every component | #daf1db via --color-grass-4 |
--color-content-brand | semantic every component | #2a7e3b via --color-grass-11 |
--color-content-default-secondary | semantic every component | #646464 via --color-gray-11 |
--color-content-utility-danger | semantic every component | #ce2c31 via --color-red-11 |
--radius-pill | semantic every component | 9999px via --radius-full |
--transition-fast | semantic every component | 150ms via --duration-150 |
--typography-label-xs-font-size | semantic every component | clamp(0.625rem, 0.56rem + 0.32vw, 0.75rem) via --font-size-100 |
--spacing-050 | primitive every component | 0.125rem |
--spacing-100 | primitive every component | 0.25rem |
--spacing-200 | primitive every component | 0.5rem |
--spacing-300 | primitive every component | 0.75rem |