On this page
Disclosure
Show and hide non-critical, contextual content in place
- Overview
- Rules and guidance
- Properties
- Styles
- Accessibility
When to use
- To make a page easier to scan when it contains information that only some users will need
- For supporting explanations that users are unlikely to need on repeat visits
When not to use
- When the information is critical, or a majority of users will need it - forcing most users to make an extra click slows down task completion, and some users might miss it altogether. Show the information instead.
- In a group - for instance, to show a list of frequently asked questions. Use Accordion instead, unless the content is inside a constrained layout such as a Card or narrow sidebar, where Accordion would be disproportionate.
- To switch between distinct sections of content - Disclosure is for revealing detail in place, not for navigation between views. Use Tabs instead.
- For brief supplementary information about a specific element - Disclosure is for longer content that benefits from being read in context. Use Tooltip instead.
- For substantial content that warrants its own focus - it may be more appropriate to use Modal instead.
Anatomy
- Caret
- Title
- Content indent
- Disclosure content
Keyboard support
Focus order
- Caret and title
Keyboard functions
- Tab - Moves keyboard focus to Disclosure
- Space or Enter - Toggles the expanded/collapsed state of the disclosure
Basic usage
Disclosure uses the native HTML details and summary elements. This means open and close behaviour is handled by the browser without JavaScript.
Edit live code
<Disclosure title="What is a carbon footprint?"> <P>A person's carbon footprint is made up of all the carbon that’s released through actions they take and choices they make, in their day-to-day lives.</P> </Disclosure>
Variants and features
Expanded by default
Disclosure is an uncontrolled component and manages its own state. The default state can be set with the open prop.
Edit live code
<Disclosure title="What is a carbon footprint?" open> <P>A person's carbon footprint is made up of all the carbon that's released through actions they take and choices they make, in their day-to-day lives.</P> </Disclosure>
usage
- Disclosure must not hide critical informationCopy rule ID for disclosure.no-critical-content
- Disclosure should not be used when the majority of users will need the contentForcing most users to make an extra click slows down task completion and some users may miss the content altogether.Copy rule ID for disclosure.no-majority-content
- Disclosure should not be used to switch between distinct sections of contentDisclosure is for revealing detail in place, not for navigation between views. Use Tabs instead.Copy rule ID for disclosure.no-navigation
- Disclosure should not be used in a groupUse Accordion instead, which is designed for this purpose.Exception: content must fit within a constrained layout where a full Accordion would be visually disproportionate, such as inside a Card or narrow sidebar columnCopy rule ID for disclosure.no-grouping
content
- Disclosure title must clearly describe the content it will revealUsers decide whether to expand a Disclosure based on its title. A vague title means users may miss information they need or expand content that is irrelevant to them.Copy rule ID for disclosure.title.clearly-descriptive
- Disclosure title should avoid sounding like it will take the user to another pageLanguage that implies navigation may dissuade users from clicking even when they need the information.Copy rule ID for disclosure.title.no-navigation-language
- Disclosure title should not be longer than a single short sentenceCopy rule ID for disclosure.title.single-sentence
- Disclosure content should not be complex or contain a large amount of contentRevealing a large amount of content in place can disrupt the user's position on the page and makes it harder to reorient.Copy rule ID for disclosure.content.no-large-content
interaction
- Disclosure will render as a native HTML details/summary element. The browser provides the expanded and collapsed state, focus management, and aria-expanded on the summary without any additional propsCopy rule ID for disclosure.will-native-details
- Disclosure will always be toggleable between expanded and collapsed states. The component manages its own toggle stateCopy rule ID for disclosure.always-toggleable
composition
- Disclosure content must not contain another DisclosureNesting creates disorientation and makes it hard for users to track where they are.Copy rule ID for disclosure.content.no-nested-disclosure
- Disclosure content must not contain a primary buttonBy its nature, Disclosure content is supplementary and should not contain primary actions.Copy rule ID for disclosure.content.no-primary-button
- Disclosure content should not contain a TextLinkThe Disclosure title is already styled as a link - additional links inside the content may create ambiguity about what is navigation and what reveals detail.Copy rule ID for disclosure.content.no-text-link
- Disclosure content may contain a secondary button, using CTALink or CTAButton depending on whether the action navigates or triggers behaviourCopy rule ID for disclosure.content.secondary-button
Disclosure
Also accepts all props from DetailsHTMLAttributes, HTMLAttributes.
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
children | ReactNode | — | No | Content revealed when the disclosure is open. |
title | ReactNode | — | Yes | Content of the clickable summary that opens and closes the disclosure. |
expanded | boolean | — | No | Opens the disclosure when `true`. Works like the native `open` attribute, and `false` does not close a disclosure that has `open` set. |
onToggle | (open: boolean) => void | — | No | Called with the new open state whenever the disclosure is opened or closed. |
open | boolean | — | No | Opens the disclosure when `true`; the native `details` attribute. `expanded` does the same. |
Styles
disclosure-summary
background: none;
border: none;
border-radius: 0;
padding: 0;
margin: 0;
font-family: ${fonts.body};
font-size: ${responsiveFontSizes.body[0]};
line-height: ${lineHeights.body};
font-weight: inherit;
text-decoration: underline;
text-align: left;
color: ${colors.primary};
position: relative;
cursor: pointer;
&::-webkit-details-marker,
&::marker {
display: none;
}
list-style: none;
display: flex;
align-items: center;
${mediaQueries.smallAndUp} {
font-size: ${responsiveFontSizes.body[1]};
}
&:focus-visible {
${focusRing}
}
icon-wrapper
display: inline-flex;
details[open] & {
transform: rotate(90deg);
}
line-indent
position: absolute;
top: 0;
bottom: 0;
width: ${borderWidths.heavier};
border-radius: ${radii.standard};
left: 0.2rem;
background-color: ${colors.borderMuted};
${mediaQueries.smallAndUp} {
left: 0.3rem;
}
disclosure-panel
position: relative;
box-sizing: border-box;
margin-top: ${space[2]};
padding-left: ${responsiveFontSizes.body[0] + space[1]};
${mediaQueries.smallAndUp} {
margin-top: ${space[3]};
padding-left: ${responsiveFontSizes.body[1] + space[2]};
}
In brief
Disclosure is a native details element with a summary for its title. The browser owns the keyboard model, the open state and keeping closed content out of reach.
What Nebula provides
- The title is a native summary, so it is a tab stop that opens and closes with the keyboard, with a visible focus ring.
- Nebula sets no ARIA attributes of its own: the browser exposes the open state.
- The caret is an Icon, so it is hidden from screen readers.
Keyboard behaviour
The title is a single tab stop, reached with Tab.
Interactions
- Tab - Moves focus to the title
- Enter or Space - Opens or closes the content
Accessible design
Write a title that says what opens
The title is the only name a keyboard or screen reader user has for the hidden content. "How is my carbon footprint calculated?" says more than "Find out more".
WCAG: 2.4.6 Headings and Labels
Accessible development
Avoid interactive elements in the title
The whole title is the control that opens the Disclosure, so a link or button inside it competes with it for the same click and key press.
WCAG: 4.1.2 Name, Role, Value
Accessibility testing status
Reviewed on 9 October 2026 against v17.0.1.
| Test | Status | Tested with |
|---|---|---|
| Default state | Tested | axe-core via the Storybook test runner (CI) |
| Advanced states | Partially tested | axe-core via the Storybook test runner (CI) |
| Keyboard navigation | Manually tested | keyboard (reported by the owner) |
| Screen reader | Partially tested | VoiceOver with Chrome (reported by the owner) |
What these tests and statuses mean
The table records which checks were run on this component on its own. It is not a statement of WCAG conformance, and it does not cover how the component is used.
The tests
- Default state: The component as it first appears, before anything is clicked or changed.
- Advanced states: Every other state and variant: error, open, selected, each size and style, and hovering.
- Keyboard navigation: Whether every function can be reached and used with the keyboard alone, with a visible focus ring.
- Screen reader: Whether a screen reader announces what is on screen correctly: the name, the role and any state.
The statuses
- Tested: Every check in this row passed in an automated run that repeats on every pull request.
- Manually tested: Every check in this row was run once, by a person or with a tool they started, and all of them passed. It is not re-run on every change.
- Partially tested: Some checks in this row were run once and passed; the rest are still to do.
- Issue found: A check in this row failed. The ticket is shown beside the status.
- Not tested: No check in this row has been run yet.
- Not applicable: This row does not apply to the component, for the reason given beside it.