shadcn.io is an independent project built on shadcn/ui
Getting started, Billing, Integrations, and Security. Each trigger stacks a title over a muted subtitle, with a plus on the right that turns into a minus. Getting started starts open.
Use it when both a summary and a plain toggle matter. If people compare sections side by side, use Tabs. In React, Base UI does not remember which topic was open.
Installation
Anatomy

Usage
<Accordion
className="w-full max-w-md -space-y-px"
defaultValue={["getting-started"]}
>
{items.map((item) => (
<AccordionItem
className="overflow-hidden border bg-background px-4 first:rounded-t-lg last:rounded-b-lg"
key={item.value}
value={item.value}
>
<AccordionTrigger className="hover:no-underline **:data-[slot=accordion-trigger-icon]:hidden">
<span className="flex w-full items-center justify-between gap-3">
<span className="flex flex-col items-start text-start">
<span>{item.title}</span>
<span className="text-muted-foreground text-sm">
{item.subtitle}
</span>
</span>
<span className="relative size-4 shrink-0">
<PlusIcon
aria-hidden="true"
className="absolute inset-0 size-4 text-muted-foreground transition-opacity duration-200 group-aria-expanded/accordion-trigger:opacity-0"
/>
<MinusIcon
aria-hidden="true"
className="absolute inset-0 size-4 text-muted-foreground opacity-0 transition-opacity duration-200 group-aria-expanded/accordion-trigger:opacity-100"
/>
</span>
</span>
</AccordionTrigger>
<AccordionContent>
{/* The rest of the file is under Installation. */}FAQ
How is the subtitle marked up?
Each item stores a subtitle under its title. They stack in flex flex-col items-start text-start, and the subtitle is text-sm text-muted-foreground.
How does the plus turn into a minus?
**:data-[slot=accordion-trigger-icon]:hidden on AccordionTrigger hides the built-in chevron. PlusIcon and MinusIcon share one relative size-4 box, and group-aria-expanded/accordion-trigger fades the plus out and the minus in over duration-200. Both icons are aria-hidden and text-muted-foreground.
Why does Getting started start open?
defaultValue={["getting-started"]} opens Getting started on first render. The string matches that item's value.
How do I let several items stay open at once?
One open item is the default. Add multiple to Accordion to let several stay open, and list every item that should start open in the defaultValue array.
API Reference
Accordion
Sets defaultValue={["getting-started"]} and value={item.value}. The rest is on the Accordion page.



