Pills that grow into cards over a product photo, on a CSS-only glass material: one open at a time, stepped with Previous and Next.
Installation
Add it with the shadcn CLI, or copy the source by hand.
$ pnpm dlx shadcn@latest add @ssntl/pill-accordionAPI reference
PillAccordion
value?Type:string | nullThe open item's value, or null when every item is a pill.Default:—defaultValue?Type:string | nullThe item open on mount, when uncontrolled.Default:nullonValueChange?Type:(value: string | null) => voidDefault:—
Also takes every prop of <div>.
PillAccordionList
aria-labelrequiredType:stringNames the set: “Features of the studio plan”.Default:—
Also takes every prop of <ul>.
PillAccordionItem
valuerequiredType:stringA unique value for the item.Default:—
Also takes every prop of <li>.
No props of their own: each passes every prop to the element on the right.
PillAccordionTrigger<button>PillAccordionTriggerIcon<span>PillAccordionContent<div>PillAccordionPrevious<button>PillAccordionNext<button>PillAccordionClose<button>
Rules
What this component expects from you, as it ships in components/ui/pill-accordion.md next to the code. The full file adds when to use it, keyboard, the UI foundations it applies and every shared rule.
## Rules for Pill accordion
- **One open at a time.** The pill grows into a card while the others make room; focus moves into the card, and Escape or Close returns it to the pill.
- Previous and Next step between cards without closing; at the ends they stay focusable (`aria-disabled`) so focus never drops to the page.
- The morph animates the item's size over 400ms on `--ease-in-out`; the label leaves at once, and the text arrives only once the card is two-thirds grown, lifting 8px, so it never shows clipped. Reduced motion: the size changes at once and the text only fades.
- **Glass.** The glass utility, clear enough to see the photo through and measured at 4.5:1 or more with pure black or white behind it, in both themes; with reduced transparency it turns solid.
- **Hit areas.** Pills are 56px tall; the round buttons are 40px discs inside a 48px target.
- Name the buttons for what they step through (“Next feature”), and keep each card to a sentence or two.
- Drive a photo beside it with value and `onValueChange`; cross-fade with opacity, keeping every photo mounted.




