UI

An interactive component which expands/collapses a panel.

Installation

npx shadcn@latest add @fulldev/collapsible

Usage

import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from "@/components/ui/collapsible"
<Collapsible>
  <CollapsibleTrigger>Can I use this in my project?</CollapsibleTrigger>
  <CollapsibleContent>
    Yes. Free to use for personal and commercial projects. No attribution
    required.
  </CollapsibleContent>
</Collapsible>

CollapsibleTrigger renders a button. To style it as a button, pass class={buttonVariants({ variant: "ghost" })}.

Composition

Collapsible
├── CollapsibleTrigger
└── CollapsibleContent

Open State

Use defaultOpen to render the collapsible expanded on first load. The root fires collapsible:change with detail.open and accepts a collapsible:set event with { open: boolean } to open or close it from a script.

<Collapsible defaultOpen>
  <CollapsibleTrigger>Toggle</CollapsibleTrigger>
  <CollapsibleContent>Content</CollapsibleContent>
</Collapsible>

Dismissal

Use closeOnEscape and closeOnClickOutside for disclosures such as a navigation panel. Both are off by default. Escape returns focus to the trigger when focus was inside the collapsible. Nested popovers and dialogs close before the panel, and their portaled content counts as inside it.

Basic

Style the open state with data-[state=open]: on the root and group-aria-expanded/button: inside a trigger styled with buttonVariants.

Settings Panel

Use a trigger button to reveal additional settings.

File Tree

Use nested collapsibles to build a file tree.

RTL

API Reference

Source: src/components/ui/collapsible

PropTypeDefaultDescription
defaultOpenbooleanfalseOpens the content on first load.
hiddenUntilFoundbooleanfalseUses hidden="until-found" so find-in-page reveals content.
closeOnEscapebooleanfalseCloses on Escape and restores focus to the trigger when focus was inside.
closeOnClickOutsidebooleanfalseCloses on a pointer press outside the collapsible.

The root and the content get data-state="open" or data-state="closed", and the trigger gets aria-expanded. See the data-slot docs for the events.

For stacked FAQ patterns with multiple items, prefer Accordion.