Collapsible
Introduction
An interactive component that can be expanded or collapsed to show or hide content.
Usage
Basic Collapsible
Additional details go here.
Additional details go here.
import { Collapsible } from "../components/ui";
export default function MyPage() {
return (
<Collapsible
trigger="Show more"
content={<p>Additional details go here.</p>}
defaultOpen
/>
);
}
With Indicator and Controlled State
import { Collapsible } from "../components/ui";
export default function MyPage() {
return (
<Collapsible
trigger="Details"
content={<p>Content revealed on toggle.</p>}
indicatorPlacement="start"
onOpenChange={(open) => console.log("open:", open)}
/>
);
}
CMS Page Builder
This component is available as a collapsible block in the Page Builder (content/pages/*.json). trigger is a nested block list (the CMS always submits an array, even for a single trigger element):
{
"type": "collapsible",
"trigger": [{ "type": "button", "text": "Show more" }],
"showIndicator": true,
"children": [
{ "type": "text", "content": "Additional details go here." }
]
}
Props
| Prop | Type | Description |
|---|
| trigger | `JSX.Element \ | string` | The trigger element or string. A string is wrapped in a button. |
| content | JSX.Element | The content to be shown or hidden. |
| indicator | JSX.Element | Optional indicator element (e.g. a chevron). |
| indicatorPlacement | `"start" \ | "end"` | Where to place the indicator relative to the trigger. Default: "end". |
| open | boolean | Whether the collapsible is open (controlled). |
| defaultOpen | boolean | Whether the collapsible is open by default (uncontrolled). |
| onOpenChange | (open: boolean) => void | Callback for when the open state changes. |
| disabled | boolean | Whether the collapsible is disabled. |
| interactive | boolean | Enable client-side interactivity. Collapsible is Tier-1 (auto-interactive): it always hydrates as an island unless you pass interactive={false}. |
| class | string | Root element class name. |
| triggerClass | string | Trigger element class name. |
| contentClass | string | Content element class name. |
| indicatorClass | string | Indicator element class name. |
| id | string | ID for the collapsible. |
Hydration
Collapsible is classified as Tier-1 (auto-interactive).
- It always renders as a hydrated client island (it needs JS to expand/collapse and to run
onOpenChange). - The only way to opt out of hydration is to pass
interactive={false}, in which case it renders the static*-primitivemarkup without the toggle behavior. - This is implemented via the shared
shouldHydrate(interactive, true)predicate inapp/components/ui/island-utils.ts, the single source of truth for all hydration decisions.