Chip group

Filter by a few facets with chips that morph as you pick them.

chipsfiltertoggle
Preview
Chip group preview

When to use

  • Facet filters people toggle often, like topics or categories.
  • Single clearable choices shown as chips, via multiple={false}.
  • Long option sets folded behind a +N more chip with maxVisible.

When not to use

  • Use multi-select when space is tight.
  • Use checkbox in forms.
  • Use segmented-control for one choice among a few views.

shadcn CLI

Also installs (1)

  • manicat-foundation
Manual install(+)
registry.jsonjson
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "chip-group",
  "type": "registry:ui",
  "title": "Chip group",
  "description": "Filter by a few facets with chips that morph as you pick them.",
  "categories": [
    "inputs"
  ],
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://manicat.viraza.net/r/manicat-foundation.json"
  ],
  "files": [
    {
      "path": "registry/components/chip-group/chip-group.tsx",
      "type": "registry:component",
      "target": "@components/manicat/chip-group/chip-group.tsx"
    },
    {
      "path": "registry/components/chip-group/chip-group.module.css",
      "type": "registry:component",
      "target": "@components/manicat/chip-group/chip-group.module.css"
    }
  ],
  "docs": "Docs and live preview: https://uiarc.dev/components/chip-group",
  "meta": {
    "tier": "free",
    "kind": "component",
    "docs": "https://manicat.viraza.net/components/chip-group",
    "markdown": "https://uiarc.dev/components/chip-group/markdown",
    "tags": [
      "chips",
      "filter",
      "toggle"
    ]
  }
}

Usage

Install the component, then copy this into your app. Change the content and the props to fit your screen.

example.tsxtsx
"use client";

import { useState } from "react";
import { ChipGroup } from "@/components/manicat/chip-group/chip-group";

const chipOptions = [
  { value: "react", label: "React" },
  { value: "motion", label: "Motion" },
  { value: "charts", label: "Charts" },
  { value: "forms", label: "Forms" },
  { value: "tables", label: "Tables" },
  { value: "text", label: "Text effects" },
];

export function ChipGroupExample() {
  const [value, setValue] = useState(["react", "charts"]);

  return <ChipGroup label="Topics" multiple options={chipOptions} value={value} onValueChange={setValue} maxVisible={3} />;
}

Examples

Real screens rather than isolated props. Switch to Code to copy a whole example into your project.

Topic filter Chips for filtering a feed; overflow collapses into a +N chip.

Topic filter Chips for filtering a feed; overflow collapses into a +N chip. preview

Keyboard interactions

KeysAction
Arrow keysMove focus between chips and the more chip, wrapping.
Home / EndFocus the first or last chip.
Enter / SpaceToggles the focused chip or opens the overflow.

Accessibility

  • The group has role="group" and aria-label; each chip is a button with aria-pressed.
  • Roving tabindex keeps one chip in the tab order; the more chip uses aria-expanded.
  • Check icons and surfaces are aria-hidden.

Motion

  • Selecting grows a check in, slides the label over, and springs the chip edge while neighbours glide to new places, even across lines. Revealed chips stagger in and the group height morphs.
  • Reduced motion replaces the morphs with short fades.

Responsive behavior

  • Chips wrap onto new lines and the frame height follows on a spring.
  • Selected chips always stay visible, even beyond maxVisible, so folding never hides active filters.

Performance

  • Every chip has layout position animation and its own ResizeObserver; keep sets to a few dozen and fold the rest.
  • Revealed chips stagger in, capped at 0.3s total.

Notes for AI

  • Use for facet filters people toggle often. Use multi-select when space is tight and checkbox in forms.
  • Always controlled. Set multiple={false} for a single, clearable choice.
  • Exported as both named and default.