Disclosure
A disclosure hides one block of content behind a button. It is Headless
UI's Disclosure in a bordered card: the button spans the top, the
chevron turns when open, and the panel unmounts while closed. For a
stack of these where only one is open at a time, use
Accordion.
import Disclosure from '@zuilib/primitives/disclosure'
Basic
Loading example
Open by default
defaultOpen sets the initial state and the button owns it from there;
pass open / onOpenChange to control it instead. The current state is
also readable from data-state on the root.
Loading example
With form controls
panelClassName is merged onto the panel, which is the usual place for
spacing between fields. title accepts any node.
Loading example
Props
DisclosureProps extends the <div> attributes of the root card
(minus title and children) with:
| Prop | Type | Default | Description |
|---|---|---|---|
titlerequired | ReactNode | — | Contents of the toggle button |
childrenrequired | ReactNode | — | Contents of the panel; unmounted while closed |
open | boolean | — | Controlled open state; use defaultOpen for uncontrolled |
defaultOpen | boolean | false | Uncontrolled initial state |
onOpenChange | (open: boolean) => void | — | Called with the next state on every toggle |
className | string | — | Merged last onto the root card |
buttonClassName | string | — | Merged last onto the toggle button |
panelClassName | string | — | Merged last onto the panel |
Slots
| Slot | Element | Notes |
|---|---|---|
[data-slot="disclosure"] | div | Root card. data-state="open" | "closed" |
[data-slot="disclosure-button"] | button | The toggle. Headless UI adds data-open, data-hover, data-focus, data-disabled |
[data-slot="disclosure-title"] | span | Wraps title inside the button |
[data-slot="disclosure-icon"] | svg | Chevron; rotated 180° while open |
[data-slot="disclosure-panel"] | div | The content; present only while open |
/* Consumer CSS: flat, borderless disclosures */
[data-slot="disclosure"] {
border: 0;
border-radius: 0;
}
[data-slot="disclosure"][data-state="open"] > [data-slot="disclosure-button"] {
background-color: var(--muted);
}
Tokens
| Token | Used for |
|---|---|
--border, --card | Card border and background |
--foreground, --muted-foreground | Title text and chevron |
--muted | Button hover (at 50%) |
--radius-lg | Card corners |
--ring | Keyboard focus ring (inset) |
--duration-fast, --duration-normal | Hover colour and chevron rotation |
Accessibility
- The toggle is a real
<button>witharia-expandedandaria-controlspointing at the panel (Headless UI). - Enter and Space toggle; the button is in the normal tab order.
- Keyboard focus draws an inset 2px
--ringring so it stays inside the card's rounded border. - The chevron rotation respects
prefers-reduced-motion. - The panel is unmounted while closed, so hidden content is not reachable by assistive technology or tab.