Components

Collapsible

An interactive panel that expands and collapses a region of content, driven by a single trigger element.

Basic usage

Compose Collapsible, a CollapsibleTrigger, and CollapsibleContent. Pass defaultOpen for an uncontrolled panel. Unlike Accordion, the three parts ship completely unstyled — they only attach data-slot hooks, so every border, spacing and animation below is yours to supply.

Engineering team
@thanh
@felix
@minh

Custom trigger

Use asChild to make any element the trigger — here a full-width Button. The content is unmounted while collapsed unless you set forceMount.

Animating the panel

Out of the box the panel snaps open. To slide it, add three classes to CollapsibleContent:

overflow-hidden data-[state=open]:animate-collapsible-down data-[state=closed]:animate-collapsible-up

The keyframes come from tw-animate-css, which @comitor/ui/styles.css already imports — there is nothing to add to your Tailwind config. They read the --radix-collapsible-content-height variable Radix measures, which is why overflow-hidden is not optional: without it the content spills out mid-slide. This is the same recipe SidebarGroup and SidebarMenuItem use in @comitor/ui/shell.

Release notes

Props

Every part forwards the full Radix prop set and exports its own prop type — CollapsibleProps, CollapsibleTriggerProps and CollapsibleContentProps.

Collapsible — the root that owns the open state.

PropTypeDefaultDescription
defaultOpenbooleanfalseOpen state when the component is uncontrolled. Use this for self-managed panels.
openbooleanControlled open state. Pair with onOpenChange to drive the panel yourself.
onOpenChange(open: boolean) => voidCalled whenever the open state changes, including via keyboard.
disabledbooleanfalseNatively disables the trigger button and stamps data-disabled on all three parts for styling.
classNamestringAdditional Tailwind classes. The root ships with no styling of its own, so this is the only layout you get.

CollapsibleTrigger — the control that toggles the panel.

PropTypeDefaultDescription
asChildbooleanfalseMerges props onto its single child instead of rendering a bare button — use to wire up a Button.
classNamestringAdditional Tailwind classes. Nothing is applied by default.

CollapsibleContent — the region that expands and collapses.

PropTypeDefaultDescription
forceMounttrueKeeps the content in the DOM while closed so you can drive the exit with your own animation library. Radix types it as the literal true — omit the prop instead of passing false.
classNamestringAdditional Tailwind classes. Add overflow-hidden plus the animate-collapsible-* pair here to get the slide.

Accessibility

  • The trigger exposes aria-expanded and aria-controls, wiring it to the content region automatically.
  • The trigger is a native button, so Enter and Space toggle the panel out of the box.
  • When using asChild, give icon-only triggers an aria-label so screen readers announce their purpose.
  • Setting disabled propagates data-disabled to every part for consistent styling and behavior.
  • Because the parts are unstyled, the disabled and focus states are yours too — style them off data-disabled and focus-visible, or drive the trigger with a Button, which already carries both.