Collapsible
An interactive section that can be toggled open or closed. Built on @base-ui/react/collapsible. Unlike Accordion, Collapsible is a single standalone region — not a group of items.
Anatomy
The root <Collapsible> wraps a <CollapsibleTrigger> (the toggle control) and a <CollapsibleContent> (the collapsible body).
Collapsible root
Always visible item
Basic Usage
The trigger can be any interactive element. The content panel animates open and closed.
3 dependencies tagged
@radix-ui/primitives
Button Trigger
Style the trigger with button classes for more prominent "Show more" expanders. Use controlled state to toggle the label.
This is the always-visible summary content. It gives enough context to decide whether the full details are needed.
Design Guidelines
Do
- Use for a single expandable region. Collapsible is for one section; Accordion is for a list of related sections.
- Always show some content by default. The always-visible part should give enough context for the user to decide whether to expand.
- Indicate state clearly. Rotate a chevron icon or swap trigger labels to show whether the panel is open or closed.
Don't
- Don't hide required information. If the content is mandatory to complete a task, show it directly.
- Don't use for navigation. Collapsible is for content disclosure, not for routing between pages.
- Don't forget the trigger label. Icon-only triggers need an
aria-labelfor screen readers.
Developer Reference
Accessibility
CollapsibleTriggerrenders as a<button>witharia-expandedmanaged automatically.- Use the
renderprop to replace the default button element — pass a function or React element (Base UI render prop, notasChild). - Control open state with
open+onOpenChange, or usedefaultOpenfor uncontrolled. - Keyboard: Space / Enter toggle the panel when the trigger is focused.
Usage
import {
Collapsible, CollapsibleTrigger, CollapsibleContent
} from "@/components/ui/collapsible"
// Basic (uncontrolled)
<Collapsible>
<div className="flex items-center justify-between">
<h4 className="text-sm font-semibold">3 items tagged</h4>
<CollapsibleTrigger className="inline-flex size-8 items-center justify-center rounded-lg border">
<ChevronDown className="size-4" />
</CollapsibleTrigger>
</div>
<div className="rounded-md border px-4 py-3 text-sm">
@radix-ui/primitives
</div>
<CollapsibleContent className="space-y-2">
<div className="rounded-md border px-4 py-3 text-sm">@radix-ui/colors</div>
<div className="rounded-md border px-4 py-3 text-sm">@base-ui/react</div>
</CollapsibleContent>
</Collapsible>
// Controlled with toggling label
const [open, setOpen] = useState(false)
<Collapsible open={open} onOpenChange={setOpen}>
<CollapsibleContent>Content here</CollapsibleContent>
<CollapsibleTrigger className={cn(buttonVariants({ variant: "outline", size: "sm" }), "w-full")}>
{open ? "Show less" : "Show more"}
</CollapsibleTrigger>
</Collapsible>
// Custom element via render prop (Base UI pattern — not asChild)
<CollapsibleTrigger render={(props) => <button {...props} className="my-btn" />}>
Toggle
</CollapsibleTrigger>