Chip Group
Single-select pill toggles — a horizontal row where exactly one chip is active. Each option carries a tone (neutral, neutral-strong, brand, or amber) that colors its active state. Arrow keys move, Enter or Space select. Form-associated; emits a composed change event.
Preview
Set the options property to a list of { value, label, tone? }. Exactly one chip is active, tracked by value.
<esa-chip-group label="Status filter" value="open"></esa-chip-group>
<script>
document.querySelector('esa-chip-group').options = [
{ value: 'all', label: 'All', tone: 'neutral' },
{ value: 'open', label: 'Open', tone: 'brand' },
{ value: 'flagged', label: 'Flagged', tone: 'amber' },
];
</script> Tones
Each option's tone sets the palette of its active state, mapped to Ecology semantic tokens. neutral is the default.
{ value: 'n', label: 'Neutral', tone: 'neutral' }
{ value: 'ns', label: 'Neutral strong', tone: 'neutral-strong' }
{ value: 't', label: 'Brand', tone: 'brand' }
{ value: 'a', label: 'Amber', tone: 'amber' } Sizes
Chips follow the shared form size scale.
<esa-chip-group size="xs" ...></esa-chip-group>
<esa-chip-group size="sm" ...></esa-chip-group>
<esa-chip-group size="md" ...></esa-chip-group>
<esa-chip-group size="lg" ...></esa-chip-group> API
| Prop | Type | Default | Description |
|---|---|---|---|
options | EsaChipOption[] | string | [] | Array of {'{ value, label, tone? }'}, or a JSON string of the same when set as an attribute. tone is one of neutral, neutral-strong, brand, amber. |
value | string | '' | The selected option value. Exactly one chip is active at a time. |
size | 'xs' | 'sm' | 'md' | 'lg' | 'md' | Chip size on the shared form scale. |
name | string | '' | Field name the selected value is submitted under. |
label | string | '' | Accessible label applied to the radiogroup (aria-label). |
Events
| Event | Type | Default | Description |
|---|---|---|---|
change | CustomEvent<{ value: string }> | — | Fired when the selection changes via click or keyboard. Composed and bubbling; detail.value is the newly selected value. |
Accessibility
- The host carries
role="radiogroup"labeled bylabel(aria-label). - Each chip is a
role="radio"witharia-checked; only the active chip is in the tab order (roving tabindex). - Arrow keys move selection with wrap-around;
HomeandEndjump to the ends; selection follows arrow focus per the WAI-ARIA radio pattern. EnterandSpaceselect the focused chip.- The
changeevent is composed and bubbles, so it can be caught on the host or an ancestor.
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 |
|---|---|---|
--focus-ring-color | component | #65ba74 via --color-border-focus → --color-grass-8 |
--focus-ring-width | component | 2px |
--form-font-size-lg | component | clamp(0.875rem, 0.77rem + 0.52vw, 1.125rem) via --type-size-300 |
--form-font-size-md | component | clamp(0.75rem, 0.66rem + 0.44vw, 0.9375rem) via --type-size-200 |
--form-font-size-sm | component | clamp(0.625rem, 0.56rem + 0.32vw, 0.75rem) via --type-size-100 |
--form-font-size-xs | component | clamp(0.5rem, 0.44rem + 0.3vw, 0.625rem) via --type-size-050 |
--form-padding-x-lg | component | 1rem via --spacing-400 |
--form-padding-x-md | component | 0.75rem via --spacing-300 |
--form-padding-x-sm | component | 0.625rem via --spacing-250 |
--form-padding-x-xs | component | 0.5rem via --spacing-200 |
--color-border | semantic | #cecece via --color-gray-7 |
--color-border-strong | semantic | #bbbbbb via --color-gray-8 |
--color-primary-border | semantic | #b2ddb5 via --color-grass-6 |
--color-primary-strong | semantic | #2a7e3b via --color-grass-11 |
--color-primary-subtle | semantic | #f5fbf5 via --color-grass-2 |
--color-surface | semantic | #fcfcfc via --color-gray-1 |
--color-surface-sunken | semantic | #f0f0f0 via --color-gray-3 |
--color-text-primary | semantic | #202020 via --color-gray-12 |
--color-text-secondary | semantic | #646464 via --color-gray-11 |
--color-text-tertiary | semantic | #646464 via --color-gray-11 |
--color-warning-border | semantic | #f3d673 via --color-status-warning-border → --color-yellow-6 |
--color-warning-strong | semantic | #ab6400 via --color-status-warning-strong → --color-yellow-11 |
--color-warning-subtle | semantic | #fefbe9 via --color-status-warning-subtle → --color-yellow-2 |
--transition-fast | semantic | 150ms ease |
--radius-100 | primitive | 0.25rem |
--spacing-100 | primitive | 0.25rem |
--spacing-150 | primitive | 0.375rem |
--spacing-200 | primitive | 0.5rem |