Disclosure
Also called collapsible, expander, show more, details/summary, toggle section
A button that reveals or hides one associated section of content, independent of any other section.
Example
Base UI Collapsible
Native <details>
Advanced settings
Requests are retried twice with exponential backoff. Raising the timeout above 30s also raises the gateway limit, so leave it alone unless you have been told otherwise.
Both expose the same contract — a button carrying aria-expanded, and one section it controls. The primitive adds a height transition and controlled state; the native element costs no JavaScript, survives before hydration, prints expanded and is found by in-page search. Reach for the primitive when you need what it adds, not by default.
When to use it
- The content is genuinely secondary: advanced options, technical detail, a full stack trace.
- A long passage needs a “read more” so the page stays scannable.
- A row or card has detail that only some users want, and hiding it keeps the list readable.
- You were about to build an accordion for exactly one section.
When not to
- The user needs to see the information. Hidden content is read less, and no styling fixes that.
- It is an error, warning or anything the user must act on — those never collapse.
- It hides a required form field. If it must be filled in, it must be visible.
- The label cannot say what is inside. “More” gives the user nothing to decide with.
Trade-offs
- The simplest way to hide something, and `<details>` gives it to you with no JavaScript at all.
- Native `<details>` is searchable with Ctrl+F, prints expanded, and works before hydration.
- No group state to manage — nothing to coordinate, nothing to get wrong.
- Whatever is behind it gets read less. That is the entire trade.
- Opening it shifts everything below, which is jarring when the trigger sits mid-page.
- It is easy to overuse until a page is a wall of closed rows with no visible content at all.
Accessibility
What this pattern needs in order to work for everyone.
- Keyboard
- The trigger must be a button — Enter and Space toggle it. A styled `<div>` gives you neither.
- Native `<summary>` provides all of this for free, including the toggle keys.
- Never make the trigger reachable only by pointer; it is the one control that gates the content.
- Roles and state
- `aria-expanded` on the trigger is the whole contract — it is what tells the user the state before they click.
- `aria-controls` pointing at the panel is useful but supported unevenly; `aria-expanded` is the part that matters.
- Do not add `role="button"` to a real button, and do not announce the state in the label — `aria-expanded` already does.
- Focus
- Focus stays on the trigger, opening and closing. The panel is not a new context and should not steal focus; the user decides when to move into it.
In the wild
- GitHub — “Show N more” on long diffs and comment threads — one section, no group.
- Notion — The toggle block: a disclosure the user creates themselves, nested wherever they like.
Compared with
Side-by-side breakdowns of patterns that solve a similar problem.