Skip to content
WANCRAFT

F.174Forms & Inputs

Chip Select

Filter and interest chips with a springy check-in, select all / clear, a max with feedback and a +N more collapse.

NewReactMotionTailwindintermediate

Overview

Chip Select is a set of toggleable pills for filters and interests. Selecting a chip springs a check mark in and draws its stroke while the neighbours glide aside; the group can be multi-select (checkboxes) or single-select (radios). A live counter tracks the selection, Select all and Clear act on the whole set, and an optional maximum blocks further picks with a shake, an accent counter and an explanation. Long sets collapse behind a "+N more" chip that also shows how many hidden chips are selected. The whole group is a single tab stop with arrow-key navigation, optional per-chip counts, and hidden inputs so the selection submits with native forms.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/chip-select.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/chip-select.json

Method 02 · Copy and paste

  1. 1. Install the dependencies below.
  2. 2. Copy the source from the Code tab into components/ui/chip-select.tsx.
  3. 3. Import it and adjust props.
npm install motion
Dependencies
motion
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { ChipSelect, type ChipOption } from "@/components/ui/chip-select";

export function ChipSelectExample() {
  const topics: ChipOption[] = [
    { value: "design", label: "Design", count: 128 },
    { value: "motion", label: "Motion", count: 64 },
    { value: "a11y", label: "Accessibility", count: 41 },
    { value: "type", label: "Typography", count: 37 },
  ];

  return (
    <div className="w-full max-w-lg">
      <ChipSelect
        label="Interests"
        options={topics}
        name="interests"
        defaultValue={["design"]}
      />
    </div>
  );
}

03Props

PropTypeDefaultDescription
optionsChipOption[]—Required. { value, label?, count? } in display order.
value / defaultValuestring[]—Controlled selection, or the initial one when uncontrolled. Values are kept in option order.
onChange(value: string[]) => void—Called with the full selection after every toggle, Select all or Clear.
labelReactNode"Filters"Visible label that names the group.
hintReactNode—Helper text below the chips, linked with aria-describedby.
multiplebooleantrueCheckbox chips (multi-select) or radio chips (single-select).
maxnumber0Maximum selections in multi mode; 0 means no limit.
collapseAfternumber8Chips shown before the rest collapse behind "+N more"; 0 shows all.
showCountsbooleantrueShow each option's count.
showActionsbooleantrueShow Select all (when no max blocks it) and Clear in multi mode.
size"sm" | "md""md"Chip height and type size.
spring{ stiffness; damping; mass }{ 600, 30, 0.7 }Spring for the check-in and neighbour reflow.
accentstring"#FF7448"Selected border and tint, check colour, focus ring and limit feedback.
namestring—Adds one hidden input per selected value (repeated name) for native forms.
disabledbooleanfalseDisables every chip and action.

04Features

  • 01Check mark springs in and draws its stroke; neighbouring chips glide with layout animation
  • 02Multi-select checkboxes or single-select radios from one prop
  • 03Select all and Clear, with a live "n/max selected" counter
  • 04Max selections: blocked picks shake, the counter turns accent and the reason is shown and announced
  • 05"+N more" collapse that badges how many hidden chips are selected; expanding focuses the first revealed chip
  • 06Optional counts per chip; hidden inputs submit the selection with native forms
motion · springmotion · layoutinput · clickinput · keyboardinput · press

05Accessibility

  • Multi mode: chips are role="checkbox" buttons with aria-checked inside a role="group" named by the label; single mode uses role="radiogroup" and role="radio".
  • The chip set is one tab stop: arrow keys move between chips (wrapping), Home / End jump to the ends, Space or Enter toggles; in single mode arrows also select, like native radios.
  • The selection counter is linked to the group with aria-describedby; additions, removals, Select all, Clear and blocked picks are announced in a polite live region.
  • Chips at the limit stay focusable and explain why they can't be selected instead of silently doing nothing.
  • The "+N more" control is a real button with aria-expanded; counts carry screen-reader text ("128 results").
  • prefers-reduced-motion removes the spring, the stroke draw, the reflow and the shake.