Components
Tag overflow
A row of tags that shows the first few and folds the rest into a "+N" count. Choosing the count opens the rest one after another in place, and "Show less" folds them back.
pnpm dlx shadcn@latest add @caliper/tag-overflowWhen to use
Use it for
- Table cells, cards and headers where a record can have many tags.
- Filters and categories that must not take over a layout.
Skip it when
- Tags people edit; use `TagInput`.
- Two or three tags; just show them.
Decisions
Why it is built this way, so you know what to keep when you change your copy.
Behaviour
- Opens in place
- The extra tags appear where they belong, one after another, instead of in a popover that hides the row.
Usage
- A disclosure
- The count is a button that says how many it will show and whether it is open; focus stays on it.
Installation
pnpm dlx shadcn@latest add @caliper/tag-overflow
Adds its 3 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage
This is the code behind the preview above.
import { type ReactNode } from "react" import { TagOverflow } from "@/components/ui/tag-overflow" function Panel({ title, context, className = "max-w-md", children }: { title: string; context: string; className?: string; children: ReactNode }) { return ( <section className={`grid w-full gap-5 rounded-overlay border border-border bg-background p-6 shadow-resting max-sm:p-4 ${className}`}> <div className="grid gap-1"> <p className="font-medium">{title}</p> <p className="text-sm text-muted-foreground">{context}</p> </div> {children} </section> ); } export function TagOverflowDemo() { return ( <Panel title="Accounts" context="Extra tags fold into a count."> <ul className="grid gap-4 text-sm"> <li className="grid gap-2"> <span className="font-medium">Northwind Traders</span> <TagOverflow label="Northwind tags" tags={[{ label: "Enterprise", tone: "violet" }, { label: "EU", tone: "blue" }, { label: "Renewal Q1", tone: "amber" }, "SSO", "Priority support", "Annual", "Security review"]} /> </li> <li className="grid gap-2"> <span className="font-medium">Harbour & Co</span> <TagOverflow label="Harbour tags" max={2} tags={[{ label: "Startup", tone: "green" }, "Monthly", "Trial ended", "Referral"]} /> </li> </ul> </Panel> ); }
API reference
TagOverflow
component
Also accepts the native props of its root element and a ref.
Accessibility
It exposes group semantics, with aria-label and aria-expanded kept in step with state.
No custom key handling; Tab and the native activation keys do the work.
Motion
It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.