Disclosure
Rows that expand and collapse in place, alone or as an accordion.
Disclosure shows and hides a block of content under a heading. A
DisclosureGroup stacks several Disclosures into an accordion. Each row has a
DisclosureTrigger, the heading and the button that toggles it, and a
DisclosurePanel, the content it reveals. The plus icon turns to a cross when
the row is expanded.
<Disclosure>
<DisclosureTrigger>Advanced settings</DisclosureTrigger>
<DisclosurePanel>
Set a custom RPC endpoint and gas limit for this project.
</DisclosurePanel>
</Disclosure>Variants
Set variant on the DisclosureGroup and every row in it follows. A
Disclosure used on its own takes variant directly.
Default
<DisclosureGroup>
<Disclosure id="network">
<DisclosureTrigger>Network</DisclosureTrigger>
<DisclosurePanel>Requests go to Base Mainnet unless you pick Base Sepolia.</DisclosurePanel>
</Disclosure>
<Disclosure id="limits">
<DisclosureTrigger>Rate limits</DisclosureTrigger>
<DisclosurePanel>Each key allows 50 requests per second.</DisclosurePanel>
</Disclosure>
<Disclosure id="billing">
<DisclosureTrigger>Billing</DisclosureTrigger>
<DisclosurePanel>Usage is billed on the first of each month.</DisclosurePanel>
</Disclosure>
</DisclosureGroup>Plain rows at the product type size, for settings, details and other secondary content inside a page.
Divided
variant="divided" puts a rule above every row and below the last (a subtler
one in dark mode), and uses the larger brand type steps. Its main use is a list
of frequently asked questions, like the FAQ sections on base.org, but it suits
any list of expandable rows that should read as one block.
Base is a secure, low-cost, builder-friendly Ethereum L2 built to bring the next billion users onchain.
<DisclosureGroup variant="divided" defaultExpandedKeys={['what']}>
<Disclosure id="what">
<DisclosureTrigger>What is Base?</DisclosureTrigger>
<DisclosurePanel>
Base is a secure, low-cost, builder-friendly Ethereum L2 built to bring
the next billion users onchain.
</DisclosurePanel>
</Disclosure>
<Disclosure id="cost">
<DisclosureTrigger>How much does a transaction cost?</DisclosureTrigger>
<DisclosurePanel>
Most transactions cost less than a cent.
</DisclosurePanel>
</Disclosure>
<Disclosure id="start">
<DisclosureTrigger>How do I start building?</DisclosureTrigger>
<DisclosurePanel>
Read the docs and deploy your first contract in minutes.
</DisclosurePanel>
</Disclosure>
</DisclosureGroup>This replaces base-org-ui's FaqAccordion: map each question to a
DisclosureTrigger and each answer to a DisclosurePanel. base.org opens the
first row on load; do the same with defaultExpandedKeys.
Expanding rows
One at a time
A DisclosureGroup keeps one row expanded at a time: opening a row closes the
one that was open. Give each Disclosure an id, then set the rows that start
open with defaultExpandedKeys, or control them with expandedKeys and
onExpandedChange.
Several at once
Set allowsMultipleExpanded on the group to let rows open independently.
<DisclosureGroup allowsMultipleExpanded>
<Disclosure id="logs">
<DisclosureTrigger>Logs</DisclosureTrigger>
<DisclosurePanel>Logs are kept for 30 days.</DisclosurePanel>
</Disclosure>
<Disclosure id="alerts">
<DisclosureTrigger>Alerts</DisclosureTrigger>
<DisclosurePanel>Alerts go to every project owner.</DisclosurePanel>
</Disclosure>
</DisclosureGroup>Disabled
Set isDisabled on a Disclosure to lock one row, or on the group to lock them
all. A disabled row keeps its current state and its trigger dims.
<Disclosure isDisabled>
<DisclosureTrigger>Team settings</DisclosureTrigger>
<DisclosurePanel>Only owners can change team settings.</DisclosurePanel>
</Disclosure>When to use
Use Disclosure to let the reader expand content they may not need, under a heading that tells them what it holds, and DisclosureGroup to stack several of those rows as an accordion.
Use something else when:
- The sections are peer views of one object that the reader switches between. Use Tabs.
- The content belongs to a control and floats above the page. Use Popover.
- The reader must respond before they continue. Use Dialog.
- A container only needs to animate a change in its own size, with no toggle. Use Animate Height.
Usage
Do
Write a trigger that says what the panel holds, so the reader can decide whether to open it without opening it.
Don't
Hide content every reader needs, such as a required step or an error, inside a collapsed row.
The trigger renders inside a heading, level 3 by default. Set level on
DisclosureTrigger to fit the page outline.
Props
DisclosureGroup
| Prop | Type | Default |
|---|---|---|
allowsMultipleExpandedWhether multiple items can be expanded at the same time. | Typeboolean | Default— |
childrenThe children of the component. A function may be provided to alter the children based on | TypeChildrenOrFunction<DisclosureGroupRenderProps> | Default— |
classNameThe CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the | TypeClassNameOrFunction<DisclosureGroupRenderProps> | Default— |
defaultExpandedKeysThe initial expanded keys in the group (uncontrolled). | TypeIterable<Key> | Default— |
expandedKeysThe currently expanded keys in the group (controlled). | TypeIterable<Key> | Default— |
isDisabledWhether all items are disabled. | Typeboolean | Default— |
variantAppearance of every Disclosure in the group. `default` stacks plain rows. | Type"default" | "divided" | Defaultdefault |
Disclosure
| Prop | Type | Default |
|---|---|---|
childrenThe children of the component. A function may be provided to alter the children based on | TypeChildrenOrFunction<DisclosureGroupRenderProps> | Default— |
classNameThe CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the | TypeClassNameOrFunction<DisclosureGroupRenderProps> | Default— |
defaultExpandedWhether the disclosure is expanded by default (uncontrolled). | Typeboolean | Default— |
isDisabledWhether the disclosure is disabled. | Typeboolean | Default— |
isExpandedWhether the disclosure is expanded (controlled). | Typeboolean | Default— |
variantAppearance of the row. Inside a DisclosureGroup the group's variant wins. | Type"default" | "divided" | Default— |
DisclosureTrigger
| Prop | Type | Default |
|---|---|---|
childrenThe children of the component. A function may be provided to alter the children based on | TypeChildrenOrFunction<DisclosureGroupRenderProps> | Default— |
classNameThe CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the | TypeClassNameOrFunction<ButtonRenderProps> | Default— |
isDisabledWhether the button is disabled. | Typeboolean | Default— |
isPendingWhether the button is in a pending state. This disables press and hover events | Typeboolean | Default— |
levelHeading level of the element wrapping the button. Defaults to 3. | Typenumber | Default3 |
typeThe behavior of the button when used in an HTML form. | Type"button" | "submit" | "reset" | Default'button' |
DisclosurePanel
| Prop | Type | Default |
|---|---|---|
childrenrequiredThe children of the component. | TypeReactNode | Default— |
classNameThe CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the | TypeClassNameOrFunction<DisclosureGroupRenderProps> | Default— |
labelThe content to display as the label. | TypeReactNode | Default— |
labelElementTypeThe HTML element used to render the label, e.g. 'label', or 'span'. | TypeElementType | Default'label' |
roleThe accessibility role for the disclosure's panel. | Type"group" | "region" | Default'group' |
Accessibility
Disclosure wraps React Aria's Disclosure, DisclosurePanel and
DisclosureGroup. The trigger is a button inside a heading; Enter and Space
toggle it, and it carries aria-expanded and aria-controls. The panel is a
group labelled by its trigger. A collapsed panel is hidden with
hidden="until-found", so find in page still reaches its text and opens the
row.
The plus icon is decorative and hidden from assistive technology; the expanded
state is announced from aria-expanded.
The panel opens and closes with a 200ms height and fade, and the icon rotates over 200ms; both ease out. Both are instant when the reader prefers reduced motion or toggles the row from the keyboard. The panel reaches 8px past its content on the sides and top, so focus rings on links and buttons inside it are not clipped.