Collapsible
StableA heading with an arrow that shows or hides extra content when pressed.
Also known as disclosure, expander, details, show more
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
Closed by default
These settings apply to new chats only.
<Collapsible header={<span className="text-body leading-5 font-medium">Advanced options</span>}>
<p className="mt-2 pl-6 text-body leading-5 text-fg-muted">These settings apply to new chats only.</p>
</Collapsible>The heading can hold more than words, like a count or a badge.
When to use it
Hides detail that most people do not need at first behind a heading they can press. The arrow turns to show whether it is open.
Made of: Arrow · Heading · Hidden section
Use it for
- Advanced options under a simpler form.
- Long detail, such as logs or notes, that would crowd the page.
- Your own expandable section when ThinkingBlock or ToolCallCard do not fit.
Not for
- The assistant's reasoning: use ThinkingBlock.
- One step the assistant took, with its status: use ToolCallCard.
- Content that most people need to read.
Do and avoid
Round prices to the nearest dollar.
Pay by Friday or the booking is cancelled.
Do
- Make the heading say what is inside, like Sources or Full output.
- Use it to tuck away extra detail that would make the page long.
- Add space inside the hidden section yourself.
Avoid
- Do not hide anything a person must act on.
- Do not put buttons inside the heading. The whole heading is one button.
- Do not stack many of them when tabs or a table would be clearer.
On a phone
- The whole header row is the button, so the tap target is the full width. On touch screens its tap area is at least 44px tall.
- It opens by tap and has no hover state, so it works the same on a phone.
- The content grows open in place and pushes the page down, with no scrolling area of its own.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| headerrequired | ReactNode | none | Content of the toggle button, shown next to the chevron. |
| childrenrequired | ReactNode | none | Panel content. Stays mounted and is hidden with the hidden attribute once it has finished closing. |
| defaultOpen | boolean | false | Initial open state when the part keeps its own state. |
| open | boolean | none | Controls whether it is open. Use with onOpenChange; without it the part keeps its own state. |
| onOpenChange | (open: boolean) => void | none | Called with the new value when the header is pressed. |
| headingLevel | 2 | 3 | 4 | 5 | 6 | none | Wraps the header button in a heading of this level, so screen reader users can jump between sections. |
| className | string | none | Class applied to the outer wrapper. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one Collapsible switches all of this from its properties panel, across 8 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Default open | Set in Figma only | On or off |
| State | Hover, Pressed and Focus come from the browser. | Default, Hover, Pressed, Focus |
States
States this part has beyond its default look. Build each one your screen can reach. States set by a property are in the Code tab.
- opening
- The content grows open and fades in over --dur-base on --ease-arrive. It is clipped only while the height moves. Instant under reduced motion.
- closing
- The content shrinks and fades in --dur-fast, then is hidden from everyone with the hidden attribute. Instant under reduced motion.
Tokens
Change one of these and every part that uses it follows.
--fg-subtle--dur-fast--dur-base--ease-arrive
Built in
- The heading is a real button. Screen readers say whether the section is open or closed.
- Enter and Space open and close it, and the keyboard stays on the heading.
- When closed, the hidden section is hidden from everyone, so screen readers and the Tab key skip it.
- The arrow is hidden from screen readers.
- The content grows open in --dur-base and closes in --dur-fast, on --ease-arrive. It is clipped only while the height moves, so focus rings inside are not cut off once it is open.
- When people turn off motion in their system settings, it opens and closes at once.
What you need to do
- Write heading words that make sense alone, because the arrow is not read out.
- Do not put another button or link inside the heading: the heading is already a button.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide