Skip to content
omaris

Selection

Chip

MD3 chip — assist, filter, input and suggestion, in one component.

import { Chip } from 'omaris'
Learn

Examples

Kinds

One component covers all four MD3 chip kinds. What makes it a filter chip is selectable; what makes it an input chip is onremove.

Assist Input Suggestion
<script lang="ts">	import { Chip } from 'omaris';​	let selected = $state(true);</script>​<Chip>Assist</Chip><Chip selectable bind:selected>Filter</Chip><Chip onremove={() => {}} removeLabel="Remove Input">Input</Chip><Chip variant="elevated">Suggestion</Chip>

Filter bar

overflow="scroll" keeps a filter bar to one line that swipes sideways, which is what MD3 does above a list. wrap is right in a form.

<script lang="ts">	import { Chip, ChipGroup } from 'omaris';​	let picked = $state<string[]>(['Erbil']);​	function toggle(city: string) {		picked = picked.includes(city) ? picked.filter((c) => c !== city) : [...picked, city];	}</script>​<div class="w-full max-w-md px-4">	<ChipGroup label="Cities" multiple overflow="scroll">		<Chip selectable selected={picked.includes('Baghdad')} onclick={() => toggle('Baghdad')}>			Baghdad		</Chip>		<Chip selectable selected={picked.includes('Erbil')} onclick={() => toggle('Erbil')}>Erbil</Chip		>		<Chip selectable selected={picked.includes('Basra')} onclick={() => toggle('Basra')}>Basra</Chip		>		<Chip selectable selected={picked.includes('Mosul')} onclick={() => toggle('Mosul')}>Mosul</Chip		>		<Chip selectable selected={picked.includes('Duhok')} onclick={() => toggle('Duhok')}>Duhok</Chip		>		<Chip selectable selected={picked.includes('Najaf')} onclick={() => toggle('Najaf')}>Najaf</Chip		>		<Chip selectable selected={picked.includes('Karbala')} onclick={() => toggle('Karbala')}>			Karbala		</Chip>	</ChipGroup></div>

Icons and tones

check={false} keeps the icon when it is the meaning — a pin, a swatch; tone with tonal for a chip that reads as a state.

Pinned Paid Overdue Small Large
<script lang="ts">	import { Chip } from 'omaris';</script>​{#snippet pin()}	...{/snippet}​<Chip>	{#snippet start()}{@render pin()}{/snippet}	Pinned</Chip><Chip selectable selected check={false}>	{#snippet start()}{@render pin()}{/snippet}	Keeps its icon</Chip><Chip tone="success" variant="tonal">Paid</Chip><Chip tone="destructive" variant="tonal">Overdue</Chip><Chip size="sm">Small</Chip><Chip size="lg">Large</Chip>

When to use it

Use it for

  • A filter bar above a list or a Table. selectable chips in a ChipGroup with multiple, and overflow="scroll" so it stays one line on a phone.
  • Things the person entered, like tags, recipients or attached files. Input chips with onremove and a removeLabel ("Remove React").
  • A contextual assist beside content: "Add to calendar", "Open in Maps". A plain chip with an icon in start and an onclick or href.
  • Suggestions and quick replies under a composer. variant="elevated" when they float over content.
  • A person. Put an Avatar in start.

Not for

  • The primary or a secondary action of a screen → Button. A chip is small, optional and about the content next to it.
  • One choice from a fixed two to five → Segmented Button. Chips are for sets that vary, wrap and can all be off.
  • A read-only status nobody presses, like "Paid" or "Overdue" → Badge. A chip looks pressable.
  • A boolean submitted with a form → Checkbox.
  • One on/off → Switch.

Do

  • Put chips that belong together in a ChipGroup with a label. It gives the set an accessible name.
  • Pick overflow on purpose: scroll for a filter bar above a list, wrap inside a form.
  • Keep the label to a couple of words. label truncates, and a chip that wraps is a button.
  • Leave check on for filter chips. The tick tells a selected chip from a tonal one. Use check={false} only when the leading icon is the meaning, like a colour swatch.

Don't

  • Use variant="tonal" for unselected filter chips. Selected and unselected then look the same.
  • Let the × do anything but remove.
  • Grow a chip with size="lg" to make it act as a button. If it needs to be big, it is a Button.

Quick reference

tone
  • primary (default)
  • secondary
  • tertiary
  • destructive
  • success
  • warning
  • info
variant
  • outlined (default)
  • tonal
  • elevated
size
  • sm
  • md (default)
  • lg
shape
  • round (default)
  • square

Pill instead of MD3's rounded rectangle.

API

Chip

MD3 chip — assist, filter, input and suggestion, in one component.

The four MD3 chip types differ only in behaviour, so they're expressed as props rather than four components: selectable gives you a filter chip (with the tick that slides in), onremove gives you an input chip (with the trailing ×), and neither gives you assist/suggestion.

A removable chip nests a real button inside, so the × is reachable by keyboard on its own rather than being a click target painted on top.

import { Chip } from 'omaris'

Parts

Every element this renders is reachable from outside. Pass Tailwind for one part as classes={{ part: '…' }}; class covers the root and is merged last, so it always wins.

root
No description in the source yet.
label
No description in the source yet.
check
The leading tick on a filter chip: zero-width until selected.
remove
The trailing × on an input chip.

Props

variant

Defaults to 'outlined'

ChipVariant
outlined
MD3's default chip: a hairline outline on the surface.
tonal
Filled, for chips that need to read as a solid object.
elevated
Elevated — a chip floating over content.
tone

Defaults to 'primary'

ChipTone
primary
secondary
tertiary
destructive
success
warning
info
size

Defaults to 'md'

ChipSize
sm
md
lg
shape

Defaults to 'round'

ChipShape
round
square
selectable

Defaults to false

boolean

Turns the chip into a filter chip: clicking toggles selected.

selected bindable

Defaults to false

boolean

Selected state of a filter chip. Bindable.

check

Defaults to true

boolean

Hide the leading tick on a selected filter chip.

onremove
() => void

Adds the trailing ×. Called when it's pressed.

removeLabel
string

Accessible name for the × — "Remove React".

ripple

Defaults to true

boolean
class
string
classes
ChipClasses

Per-part Tailwind overrides. class still covers the root.

start
Snippet

Leading icon or avatar.

end
Snippet

Trailing icon, before the × if there is one.

children
Snippet
icon
boolean

Square, label-less button. Requires an aria-label.

confetti
boolean | ConfettiOptions

Confetti on press. true for the default burst, or any ConfettiOptions — confetti={{ preset: 'fireworks' }}.

loading
boolean

Grows a spinner in at the start of the button and blocks interaction. The label stays put; only an icon button swaps its icon out.

toggle
boolean

Turns the button into a two-state toggle driven by pressed. Ignored when href is set — a link has no pressed state.

pressed bindable
boolean

Selected state of a toggle button. Bindable.

ChipGroup

A set of chips that belong together, with the accessible name that implies.

overflow is the real decision: wrap flows onto more lines and is right in a form, scroll keeps one line that swipes sideways and is what MD3 does for a filter bar above a list.

import { ChipGroup } from 'omaris'

Props

overflow

Defaults to 'wrap'

'wrap' | 'scroll'

wrap lets the set flow onto more lines — the right choice in a form. scroll keeps it to one line that swipes sideways, which is what MD3 does for a filter bar above a list.

scroll bleeds 16px past its container on each side and restores the inset inside itself, so the strip runs to the screen edge while the first chip still lines up with the text above it. It therefore wants a container with at least px-4; in one with none, those 16px are 16px of horizontal page scroll.

label
string

Accessible name for the set.

multiple

Defaults to false

boolean

A set where chips are chosen, rather than one where they act.

class
string
children
Snippet