Skip to main content

Chip

Compact interactive labels for filtering, selecting, and tagging.

Quick start
import { Chip } from "mates-ui";

Chip("Design", { variant: "filter", selected: true });

Filter chips

import { html, atom, renderApp } from 'mates';
import { Chip, Text } from 'mates-ui';

const TAGS = ["Design", "Development", "Research", "UX", "Figma", "TypeScript", "CSS", "Animation"];

const App = () => {
const selected = atom(new Set(["Design"]));
const toggle = (tag) => {
const next = new Set(selected());
next.has(tag) ? next.delete(tag) : next.add(tag);
selected.set(next);
};
return () => html`
<x-col gap="var(--md-space-3)">
<x-row wrap gap="var(--md-space-2)">
${TAGS.map((tag) => Chip(tag, {
selected: selected().has(tag),
on: { click: () => toggle(tag) },
}))}
</x-row>
${Text(`Selected: ${[...selected()].join(", ") || "none"}`, { type: "body-sm", color: "muted" })}
</x-col>
`;
};

renderApp(App, document.getElementById('app'));

Tag chips

import { html, renderApp } from 'mates';
import { Chip } from 'mates-ui';
import { StarIcon } from 'mates-icons';

const App = () => () => html`
<x-row wrap gap="var(--md-space-2)">
${Chip("Active", { variant: "tag", tagColor: "success", dot: true })}
${Chip("Pending", { variant: "tag", tagColor: "warning", dot: true })}
${Chip("Failed", { variant: "tag", tagColor: "error", dot: true })}
${Chip("Draft", { variant: "tag", tagColor: "neutral" })}
${Chip("Primary", { variant: "tag", tagColor: "primary", icon: StarIcon() })}
${Chip("Secondary", { variant: "tag", tagColor: "secondary" })}
${Chip("Tertiary", { variant: "tag", tagColor: "tertiary" })}
${Chip("Removable", { variant: "tag", tagColor: "primary", onRemove: () => {} })}
</x-row>
`;

renderApp(App, document.getElementById('app'));

With icons

import { html, renderApp } from 'mates';
import { Chip } from 'mates-ui';
import { PhotoCameraIcon, MusicNoteIcon, LocationOnIcon, StarIcon, CalendarTodayIcon } from 'mates-icons';

const App = () => () => html`
<x-row gap="var(--md-space-2)" wrap>
${Chip("Camera", { icon: PhotoCameraIcon() })}
${Chip("Music", { icon: MusicNoteIcon(), selected: true })}
${Chip("Location", { icon: LocationOnIcon() })}
${Chip("Star", { icon: StarIcon(), selected: true })}
${Chip("Date", { icon: CalendarTodayIcon() })}
</x-row>
`;

renderApp(App, document.getElementById('app'));

Input chips

import { html, atom, renderApp } from 'mates';
import { Chip, Text } from 'mates-ui';

const App = () => {
const chips = atom(["JavaScript", "CSS", "HTML"]);
const remove = (label) => chips.set(chips().filter((c) => c !== label));
return () => html`
<x-row wrap gap="var(--md-space-2)">
${chips().map((label) => Chip(label, { variant: "input", onRemove: () => remove(label) }))}
${chips().length === 0
? Text("All chips removed. Refresh to reset.", { type: "body-sm", color: "muted" })
: html``}
</x-row>
`;
};

renderApp(App, document.getElementById('app'));

Disabled

import { html, renderApp } from 'mates';
import { Chip } from 'mates-ui';
import { LockIcon } from 'mates-icons';

const App = () => () => html`
<x-row gap="var(--md-space-2)" wrap>
${Chip("Disabled", { disabled: true })}
${Chip("Selected disabled", { disabled: true, selected: true })}
${Chip("Icon disabled", { disabled: true, icon: LockIcon() })}
</x-row>
`;

renderApp(App, document.getElementById('app'));

Assist

import { html, renderApp } from 'mates';
import { Chip } from 'mates-ui';
import { AlarmIcon, EventIcon, SendIcon, ShareIcon } from 'mates-icons';

const App = () => () => html`
<x-row gap="var(--md-space-2)" wrap>
${Chip("Add to calendar", { variant: "assist", icon: EventIcon() })}
${Chip("Set a reminder", { variant: "assist", icon: AlarmIcon() })}
${Chip("Send message", { variant: "assist", icon: SendIcon() })}
${Chip("Share", { variant: "assist", icon: ShareIcon() })}
</x-row>
`;

renderApp(App, document.getElementById('app'));

MD3 Ripple (enableRipple)

import { html, renderApp } from 'mates';
import { Chip } from 'mates-ui';
import { StarIcon, EventIcon } from 'mates-icons';

const App = () => () => html`
<x-row wrap gap="var(--md-space-2)">
${Chip("Filter", { enableRipple: true })}
${Chip("Selected", { selected: true, enableRipple: true })}
${Chip("With icon",{ icon: StarIcon(), enableRipple: true })}
${Chip("Assist", { variant: "assist", icon: EventIcon(), enableRipple: true })}
${Chip("Input", { variant: "input", onRemove: () => {}, enableRipple: true })}
${Chip("Success", { variant: "tag", tagColor: "success", dot: true, enableRipple: true })}
${Chip("Error", { variant: "tag", tagColor: "error", dot: true, enableRipple: true })}
</x-row>
`;

renderApp(App, document.getElementById('app'));

Chip

import { Chip } from "mates-ui";
Prop Type Default Description
attr AttrMap Extra HTML attributes forwarded to chip parts (`root`, `icon`, `label`, `remove`).
classes string | string[] Extra root classes — joined and appended after built-in classes.
data DataAttrMap Root `data-*` map (`testId` → `data-testid`). `testId` prop / `attr` win over `data`.
disabled boolean Disables interaction and applies muted styling.
dot boolean Renders a small status dot on tag variant chips. Ignored when icon is also set.
enableBloom boolean true When true, applies a soft bloom press effect. Set to `false` to disable all press effects (including ripple).
enableRipple boolean true When true, replaces the default soft bloom press effect with a Material Design 3-style ripple — a sharp-edged circle that grows from the contact point, with hover/focus state-layer support.
icon IconInput Icon rendered as a leading icon. Accepts a Material Symbol name (string) or a lit-html TemplateResult.
id string Root `id` shorthand (`attr.id` wins). Form native-control `id` props are unchanged.
label* string Visible text content of the chip.
on OnEventMap DOM event handlers on the root element.
onClick (e: MouseEvent) => void Shorthand for `on.click`. Fired when the chip root is clicked.
onRemove () => void Callback fired when the × button is pressed. Renders the remove button on input and tag variants.
selected boolean Whether the chip is in a selected/active state (filter variant).
style StyleMap Shorthand for `style`. Inline styles applied to the root element.
style StyleMap Inline CSS on the root element.
tagColor "neutral" | "primary" | "secondary" | "tertiary" | "error" | "warning" | "success" "neutral" Soft fill color applied to tag variant chips.
testId string Overrides the default `data-testid` attribute on the root element.
variant "filter" | "assist" | "input" | "tag" "filter" Chip style variant. Filter chips are toggleable; input chips are removable; tag chips are colored labels; assist chips trigger actions.

CSS tokens

Token Role
--md-color-on-secondary-container Selected chip label colour
--md-color-on-surface Default chip label colour
--md-color-outline Default chip border
--md-color-secondary-container Selected chip background
--md-color-surface-container-low Default chip background
--md-shape-full Pill border-radius

Caveats

  • Filter chips use role="checkbox" + aria-checked — always provide a meaningful label.
  • Tag dot and icon are mutually exclusive — icon wins if both are set.
  • onRemove is only shown on input and tag variants.