Components
An interactive component which expands and collapses a panel.
Playground
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@workspace/ui/components/collapsible"
<Collapsible defaultOpen className="flex w-full max-w-sm flex-col gap-2">
<div className="flex items-center justify-between gap-4 px-4">
<h4 className="text-sm font-medium">@westy starred 3 repositories</h4>
<CollapsibleTrigger asChild>
<Button variant="ghost" size="icon-sm">
<CaretUpDownIcon />
<span className="sr-only">Toggle</span>
</Button>
</CollapsibleTrigger>
</div>
<div className="rounded-md border px-4 py-2 font-mono text-sm">
@workspace/ui
</div>
<CollapsibleContent className="flex flex-col gap-2">
<div className="rounded-md border px-4 py-2 font-mono text-sm">
radix-ui/primitives
</div>
<div className="rounded-md border px-4 py-2 font-mono text-sm">
tailwindlabs/tailwindcss
</div>
</CollapsibleContent>
</Collapsible>open and onOpenChange to own the state from outside. A CollapsibleTrigger is optional — here a regular Button drives the panel, so the same state can also feed labels or other UI.Advanced settings
const [open, setOpen] = React.useState(false)
<div className="w-full max-w-sm space-y-2">
<div className="flex items-center justify-between gap-4">
<p className="text-sm font-medium">Advanced settings</p>
<Button variant="outline" size="sm" onClick={() => setOpen(!open)}>
{open ? "Hide" : "Show"}
</Button>
</div>
<Collapsible open={open} onOpenChange={setOpen}>
<CollapsibleContent>
<div className="space-y-1 rounded-md border px-4 py-3 text-sm">
<p className="font-medium">Danger zone</p>
<p className="text-muted-foreground">
These options are hidden by default because they affect the
whole workspace.
</p>
</div>
</CollapsibleContent>
</Collapsible>
</div>group-data-[state=open]:rotate-90 on the trigger.<Collapsible defaultOpen>
<CollapsibleTrigger className="group flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground">
<CaretRightIcon className="size-4 text-muted-foreground transition-transform group-data-[state=open]:rotate-90" />
<FolderIcon className="size-4 text-muted-foreground" />
packages/ui
</CollapsibleTrigger>
<CollapsibleContent>
<div className="ms-3 flex flex-col border-s ps-3">
{/* nested folders and files */}
</div>
</CollapsibleContent>
</Collapsible>dir prop — a single trigger has no directional keyboard behavior. Setting dir="rtl" on a wrapping element is enough, as long as the styling uses logical utilities (ps-*, ms-*, border-s).<div dir="rtl">
<Collapsible defaultOpen className="flex w-full flex-col gap-2">
<div className="flex items-center justify-between gap-4 px-4">
<h4 className="text-sm font-medium">أضاف @westy ٣ مستودعات إلى المفضلة</h4>
<CollapsibleTrigger asChild>
<Button variant="ghost" size="icon-sm">
<CaretUpDownIcon />
<span className="sr-only">تبديل</span>
</Button>
</CollapsibleTrigger>
</div>
<div className="rounded-md border px-4 py-2 font-mono text-sm">
@workspace/ui
</div>
<CollapsibleContent className="flex flex-col gap-2">
<div className="rounded-md border px-4 py-2 font-mono text-sm">
radix-ui/primitives
</div>
</CollapsibleContent>
</Collapsible>
</div>aria-expanded and aria-controls, and the content is removed from the accessibility tree (and hidden) while closed. Enter or Space toggles the panel. All three parts carry data-state="open|closed" and, when disabled, data-disabled for styling.<div data-slot="collapsible" data-state="open">
<button
data-slot="collapsible-trigger"
data-state="open"
aria-expanded="true"
aria-controls="radix-:r1:"
>
Toggle
</button>
<div data-slot="collapsible-content" data-state="open" id="radix-:r1:">
Panel content
</div>
</div>| Component | Prop | Default |
|---|---|---|
| Collapsible | defaultOpen?: boolean | false |
| Collapsible | open?: boolean, onOpenChange?: (open) => void | — |
| Collapsible | disabled?: boolean | false |
| CollapsibleTrigger | asChild?: boolean | false |
| CollapsibleContent | forceMount?: true | — |
<Collapsible data-slot="collapsible" /> // Root — unstyled state container <CollapsibleTrigger data-slot="collapsible-trigger" /> // <button aria-expanded>, toggles the panel <CollapsibleContent data-slot="collapsible-content" /> // the panel, hidden while closed
Tokens used
8 design tokens consumed by the Collapsible examples.
--accent
Accent
--accent-foreground
Accent Foreground
--muted-foreground
Muted Foreground
--border
Border
--radius-md
Radius 0.8× (8px)
--font-mono
Mono font (Geist Mono)
--text-sm
Text Small (14px)
--spacing
Spacing unit (4px)