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-label for screen readers.

Developer Reference

Accessibility

  • CollapsibleTrigger renders as a <button> with aria-expanded managed automatically.
  • Use the render prop to replace the default button element — pass a function or React element (Base UI render prop, not asChild).
  • Control open state with open + onOpenChange, or use defaultOpen for 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>