collapsible
An interactive component which expands/collapses a panel.
Philosophy
Collapsible is the simplest disclosure primitive — it shows and hides content. Unlike Accordion, it doesn't manage a group of items or enforce single-selection. Use it for individual expand/collapse needs like "show more" sections, advanced settings, or code blocks. It's the building block that Accordion is built on.
Installation
npx @gentleduck/cli add collapsible
npx @gentleduck/cli add collapsible
Usage
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible"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><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>Component Composition
API Reference
Collapsible
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | -- | Controlled open state |
onOpenChange | (open: boolean) => void | -- | Callback fired when open state changes |
defaultOpen | boolean | false | Initial open state when uncontrolled |
dir | 'ltr' | 'rtl' | -- | Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> 'ltr'). |
...props | React.HTMLProps<HTMLDivElement> | -- | Additional props to spread to the content div |
CollapsibleTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
variant | ButtonVariant | 'ghost' | Button variant passed to the underlying Button component |
children | React.ReactNode | -- | Trigger content |
onClick | React.MouseEventHandler | -- | Additional click handler; open/close toggle is handled internally |
...props | React.ComponentPropsWithoutRef<typeof Button> | -- | Additional props inherited from Button. |
CollapsibleContent
| Prop | Type | Default | Description |
|---|---|---|---|
forceMount | boolean | false | When true, content is always mounted in the DOM regardless of open state |
...props | React.HTMLProps<HTMLElement> | -- | Additional props to spread to the section element |
useCollapsible
Hook to access collapsible state from within a Collapsible tree. Throws if used outside a Collapsible.
import { useCollapsible } from "@/components/ui/collapsible"
const { open, onOpenChange } = useCollapsible()import { useCollapsible } from "@/components/ui/collapsible"
const { open, onOpenChange } = useCollapsible()| Return | Type | Description |
|---|---|---|
open | boolean | Current open state |
onOpenChange | (open: boolean) => void | Function to update open state |
wrapperRef | React.RefObject<HTMLDivElement | null> | Ref to the root collapsible element |
triggerRef | React.RefObject<HTMLButtonElement | null> | Ref to the trigger button |
contentRef | React.RefObject<HTMLDivElement | null> | Ref to the content section |
contentId | string | Auto-generated ID linking trigger and content via aria-controls |
RTL Support
Direction is resolved through the shared primitives direction module. Use a local dir="rtl" override when the component exposes it, or set DirectionProvider at app/root level for global RTL/LTR behavior.