Chips
Assist chip
Outlined
<ChipSet>
<AssistChip label="Assist chip" />
<AssistChip label="With icon">
{#snippet icon()}<Icon>bookmark</Icon>{/snippet}
</AssistChip>
</ChipSet>Elevated
<ChipSet>
<AssistChip elevated label="Assist chip" />
<AssistChip elevated label="With icon">
{#snippet icon()}<Icon>bookmark</Icon>{/snippet}
</AssistChip>
</ChipSet>Disabled
<ChipSet>
<AssistChip disabled label="Outlined" />
<AssistChip disabled label="Outlined with icon">
{#snippet icon()}<Icon>bookmark</Icon>{/snippet}
</AssistChip>
<AssistChip disabled elevated label="Elevated" />
<AssistChip disabled elevated label="Elevated with icon">
{#snippet icon()}<Icon>bookmark</Icon>{/snippet}
</AssistChip>
</ChipSet>As link
<ChipSet>
<AssistChip label="Visit website" href="https://noph.dev">
{#snippet icon()}<Icon>open_in_new</Icon>{/snippet}
</AssistChip>
</ChipSet>Filter chip
Outlined
<ChipSet>
<FilterChip label="Filter chip" />
<FilterChip label="Selected" selected />
<FilterChip label="With icon">
{#snippet icon()}<Icon>bookmark</Icon>{/snippet}
</FilterChip>
<FilterChip label="Selected with icon" selected>
{#snippet icon()}<Icon>bookmark</Icon>{/snippet}
</FilterChip>
</ChipSet>Elevated
<ChipSet>
<FilterChip elevated label="Filter chip" />
<FilterChip elevated label="Selected" selected />
<FilterChip elevated label="With icon">
{#snippet icon()}<Icon>bookmark</Icon>{/snippet}
</FilterChip>
<FilterChip elevated label="Selected with icon" selected>
{#snippet icon()}<Icon>bookmark</Icon>{/snippet}
</FilterChip>
</ChipSet>Removable
<ChipSet>
<FilterChip label="Removable" removable onremove={() => {}} />
<FilterChip label="Selected" removable selected onremove={() => {}} />
<FilterChip elevated label="Elevated" removable onremove={() => {}} />
</ChipSet>Disabled
<ChipSet>
<FilterChip disabled label="Outlined" />
<FilterChip disabled label="Outlined selected" selected />
<FilterChip disabled elevated label="Elevated" />
<FilterChip disabled elevated label="Elevated selected" selected />
<FilterChip disabled label="With icon">
{#snippet icon()}<Icon>bookmark</Icon>{/snippet}
</FilterChip>
</ChipSet>Group
let filterGroup = $state<string[]>([])
<ChipSet>
<FilterChip label="Running" value="running" bind:group={filterGroup} />
<FilterChip label="Walking" value="walking" bind:group={filterGroup} />
<FilterChip label="Cycling" value="cycling" bind:group={filterGroup} />
<FilterChip label="Swimming" value="swimming" bind:group={filterGroup} />
</ChipSet>Input chip
Default
<ChipSet>
<InputChip label="Input chip" />
<InputChip label="With icon">
{#snippet icon()}<Icon>person</Icon>{/snippet}
</InputChip>
</ChipSet>Selected
<ChipSet>
<InputChip selected label="Selected" />
<InputChip selected label="With icon">
{#snippet icon()}<Icon>person</Icon>{/snippet}
</InputChip>
</ChipSet>Separate actions
The chip body is a button of its own, so it can be focused and activated with the keyboard. Use onclick for the primary action, for example selecting the chip or switching it into
an edit mode, and onremove for the trailing icon.
<InputChip
bind:selected
label={label}
ariaLabelRemove="Remove {label}"
onclick={() => (selected = !selected)}
onremove={() => remove()}
/>Disabled
<ChipSet>
<InputChip disabled label="Disabled" />
<InputChip disabled selected label="Disabled selected" />
<InputChip disabled label="With icon">
{#snippet icon()}<Icon>person</Icon>{/snippet}
</InputChip>
</ChipSet>Chips with text fields
let pendingDeleteIndex: number | null = $state(null)
<TextField
type="email"
label="Emails"
variant="outlined"
placeholder="Add email..."
bind:value={email}
populated={emails.length > 0}
onkeydown={(e) => {
if (e.key === 'Enter') {
e.preventDefault()
if (e.currentTarget.value && e.currentTarget.reportValidity()) {
emails.push(e.currentTarget.value)
email = ''
}
} else if (e.key === 'Backspace' && !e.currentTarget.value && emails.length > 0) {
e.preventDefault()
if (pendingDeleteIndex !== null) {
emails.splice(pendingDeleteIndex, 1)
pendingDeleteIndex = null
} else {
pendingDeleteIndex = emails.length - 1
}
} else {
pendingDeleteIndex = null
}
}}
onfocus={() => { pendingDeleteIndex = null }}
>
<ChipSet chipsCount={emails.length}>
{#each emails as email, index (index)}
<InputChip
name="email"
value={email}
selected={pendingDeleteIndex === index}
onremove={() => {
if (index > -1) {
emails.splice(index, 1)
pendingDeleteIndex = null
}
}}
/>
{/each}
</ChipSet>
</TextField>Accessibility
Every chip type renders the element that matches what it does. An assist chip is a <button>, or an <a> when you pass an href. A
filter chip is a checkbox with a label, so it reports its selected state to assistive technology
on its own. An input chip is a button with a second button for removing it.
Wrap chips in a ChipSet to give them a single tab stop: Tab moves into and
out of the set, ← and → move between the chips and wrap around at the ends,
and Home and End jump to the first and the last one.
A remove button carries no text of its own, so give it one through ariaLabelRemove. The default is the bare "Remove", which does not say
what is being removed, so name the chip in it.
<InputChip
label={email}
ariaLabelRemove="Remove {email}"
onremove={() => remove(email)}
/>Theming
| Token | Default value |
|---|---|
--np-assist-chip-label-text-color | --np-color-on-surface |
--np-assist-chip-outline-color | --np-color-outline-variant |
--np-filter-chip-container-shape | --np-shape-corner-small |
--np-filter-chip-outline-color | --np-color-outline-variant |
--np-input-chip-container-shape | --np-shape-corner-small |
--np-input-chip-outline-color | --np-color-outline-variant |
The colours of a filter and an input chip come from the theme's secondary-container and on-secondary-container roles while they are
selected, and from on-surface-variant while they are not. An elevated chip takes its shadow
from the elevation roles.
Example
<FilterChip
label="Tertiary"
--np-filter-chip-container-shape="var(--np-shape-corner-full)"
--np-filter-chip-outline-color="var(--np-color-tertiary)"
/>API
ChipSet attributes
Everything you pass is forwarded to the wrapping <div>, so class, style and aria-label work as expected.
| Attribute | Type | Default | Description |
|---|---|---|---|
chipsCount | number | undefined | undefined | Number of chips in the set. Pass it when the set lives inside a text field, so the field can make room for the chips. |
AssistChip attributes
An assist chip takes the Button attributes apart from variant, start and end, which the chip sets itself. That
includes href, onclick and type.
| Attribute | Type | Default | Description |
|---|---|---|---|
label | string | '' | Text of the chip. |
icon | Snippet | undefined | undefined | Leading icon. |
elevated | boolean | false | Drops the outline and gives the chip a shadow instead. |
disabled | boolean | false | Makes the chip non-interactive. |
element | HTMLDivElement | undefined | undefined | Bindable reference to the chip element. |
FilterChip attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
label | string | '' | Text of the chip. |
selected | boolean | undefined | undefined | Bindable. Whether the filter is on. |
group | (string | number)[] | null | undefined | undefined | Bindable. Bind several chips that share a name to one array and their values are added and removed as they are toggled. |
name | string | undefined | undefined | Form field name of the underlying checkbox. |
value | string | undefined | undefined | Value submitted with the form, and the entry used in group. |
defaultSelected | boolean | null | undefined | undefined | Selected state a form reset returns the chip to. |
removable | boolean | false | Adds a trailing remove button. |
onremove | MouseEventHandler | undefined | undefined | Called when the remove button is clicked. |
ariaLabelRemove | string | 'Remove' | Accessible name of the remove button. |
icon | Snippet | undefined | undefined | Leading icon, shown while the chip is not selected. |
elevated | boolean | false | Drops the outline and gives the chip a shadow instead. |
disabled | boolean | false | Makes the chip non-interactive. |
element | HTMLDivElement | undefined | undefined | Bindable reference to the chip element. |
InputChip attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
label | string | '' | Text of the chip. Falls back to value when it is empty. |
selected | boolean | undefined | undefined | Bindable. Highlights the chip, for instance to show which one Backspace would remove next. |
name | string | undefined | undefined | Form field name. The value is submitted through a hidden input. |
value | string | number | undefined | undefined | Value submitted with the form. |
onclick | MouseEventHandler | undefined | undefined | Called when the chip itself is clicked, not the remove button. |
onremove | MouseEventHandler | undefined | undefined | Called when the remove button is clicked. |
ariaLabelRemove | string | 'Remove' | Accessible name of the remove button. |
icon | Snippet | undefined | undefined | Leading icon or avatar. |
disabled | boolean | false | Makes the chip non-interactive. |
element | HTMLDivElement | undefined | undefined | Bindable reference to the chip element. |
actionElement | HTMLButtonElement | undefined | undefined | Bindable reference to the chip's own button. |