Collapsible
A Collapsible is a single expandable section. Use it wherever content should be progressively revealed without a page transition — order summaries, stack traces, DNS settings, build logs, environment variables, and more.
This component is built on top of React Aria's Disclosure primitive, giving you managed focus, correct ARIA attributes, and keyboard interaction for free.
Installation
Install the component using the Tailgrids CLI.
npx @tailgrids/cli add collapsibleAnatomy
Import the three composable parts and assemble them.
import {
Collapsible,
CollapsibleTrigger,
CollapsibleContent
} from "@/components/collapsible";
export default function CollapsibleAnatomy() {
return (
<Collapsible>
<CollapsibleTrigger />
<CollapsibleContent />
</Collapsible>
);
}Usage
Import the three composable parts and assemble them.
import {
Collapsible,
CollapsibleTrigger,
CollapsibleContent
} from "@/registry/core/collapsible";
export default function Example() {
return (
<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>
);
}Examples
Controlled
The collapsible component can be controlled using isExpanded and onExpandedChange. In this example, we show an error summary with a "Stack trace" section that can be toggled open to reveal more details.
TypeError
Cannot read properties of undefined (reading 'map') in ProductList.tsx:24
Default Open
By default, the collapsible component is closed. You can open it by default using defaultExpanded prop on Collapsible component.
Disabled
You can use isDisabled to prevent the user from expanding or collapsing the panel.
Order Summery
With Icon
Interactive
You can create a fully interactive collapsible component using the Collapsible component.
API Reference
Collapsible
The root component. Wraps React Aria's Disclosure and accepts all its props.
| Prop | Type | Default | Description |
|---|---|---|---|
isExpanded | boolean | — | Controlled expanded state |
defaultExpanded | boolean | false | Default expanded state (uncontrolled) |
onExpandedChange | (isExpanded: boolean) => void | — | Called when the expanded state changes |
isDisabled | boolean | false | Prevents the user from expanding or collapsing |
id | Key | — | ID for use within a DisclosureGroup |
className | string | — | Additional CSS classes merged onto the root element |
children | ReactNode | — | Should contain CollapsibleTrigger and CollapsibleContent |
| Data attribute | Values | Description |
|---|---|---|
data-expanded | boolean | Set when the panel is expanded |
data-disabled | boolean | Set when isDisabled is true |
data-focus-visible-within | boolean | Set when keyboard focus is inside the component |
CollapsibleTrigger
The heading + button element that toggles the panel. Renders a semantic heading wrapping a <button slot="trigger">.
| Prop | Type | Default | Description |
|---|---|---|---|
level | 1 | 2 | 3 | 4 | 5 | 6 | 3 | HTML heading level rendered around the trigger button |
className | string | — | Additional CSS classes applied to the trigger button |
children | ReactNode | — | Trigger label — anything rendered to the left of the chevron |
CollapsibleContent
The collapsible panel that shows content when the trigger is activated. Maps to React Aria's DisclosurePanel.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes applied to the panel |
children | ReactNode | — | Content to display when the collapsible is open |
The panel is hidden from the accessibility tree when collapsed. React Aria handles the hidden attribute automatically.
Accessibility
- Semantics — The trigger is a
<button>inside a heading element (h3by default). This creates the correct heading hierarchy for screen readers. - ARIA attributes —
aria-expandedandaria-controlsare automatically managed by React Aria. No manual wiring required. - Keyboard support — Press
SpaceorEnteron the focused trigger to expand or collapse the panel. - Focus management — Focus styles are visible when navigating by keyboard (
focus-visible). - Disabled state — When
isDisabledis set, the trigger receivesdisabledand is removed from the tab order. - Heading level — Use the
levelprop onCollapsibleTriggerto match the heading hierarchy of the surrounding page content.