Disclosure
- Source: https://github.com/reach/reach-ui/tree/main/packages/disclosure
- WAI-ARIA: https://www.w3.org/TR/wai-aria-practices-1.2/#disclosure
A disclosure is a button that controls the visibility of a panel of content. When the content inside the panel is hidden, it is often styled as a typical push button with a right-pointing arrow or triangle to hint that activating the button will display additional content. When the content is visible, the arrow or triangle typically points down.
If you have a group of disclosures that stack vertically and exist within the same logical context, you may want to use @reach/accordion
instead.
Installation
From the command line in your project directory, run npm install @reach/disclosure
or yarn add @reach/disclosure
. Then import the components that you need:
npm install @reach/disclosure# oryarn add @reach/disclosure
import { Disclosure, DisclosureButton, DisclosurePanel,} from "@reach/disclosure";
Usage
function Example() { return ( <Disclosure> <DisclosureButton>Find out what lies beneath</DisclosureButton> <DisclosurePanel>Here I am! I am the buried treasure!</DisclosurePanel> </Disclosure> );}
Component API
Disclosure
The wrapper component and context provider for a disclosure's button and panel components. A disclosure should never have more than one button or panel descendants.
<Disclosure> <DisclosureButton>Do a thing</DisclosureButton> <DisclosurePanel>...</DisclosurePanel></Disclosure>
It is important to note that the Disclosure
component doesn't actually render a DOM node, so there is no way to add styles to a disclosure wrapper directly. If you want your disclosure to have a wrapper element you can nest one directly.
<Disclosure> <div style={{ padding: 10 }}> <DisclosureButton>Do a thing</DisclosureButton> <DisclosurePanel>...</DisclosurePanel> </div></Disclosure>
Controlled Disclosure
If you want to control the disclosure's value, you can do so by passing open
and onChange
props.
const [isOpen, setOpen] = React.useState(false);return ( <Disclosure open={isOpen} onChange={() => setOpen(!isOpen)}> <DisclosureButton /> <DisclosurePanel /> </Disclosure>);
Disclosure Props
Prop | Type | Required |
---|---|---|
children | node | true |
defaultOpen | boolean | false |
id | string | number | false |
onChange | func | false |
open | boolean | false |
Disclosure children
children: React.ReactNode
Disclosure
expects to receive accept DisclosureButton
and DisclosurePanel
components as either direct children or descendants. It can also accept wrapper elements if desired, though it is not recommended to pass other arbitrary components within a disclosure in most cases.
<div> {/* OK! */} <Disclosure> <DisclosureButton>Click Me</DisclosureButton> <DisclosurePanel>Collapse or open this content!</DisclosurePanel> </Disclosure> {/* Also OK! */} <Disclosure> <div> <DisclosureButton>Click Me</DisclosureButton> <DisclosurePanel>Collapse or open this content!</DisclosurePanel> </div> </Disclosure> {/* Probably confusing, you should avoid! */} <Disclosure> <div>Mary had a little lamb, little lamb, blah blah blah</div> <DisclosureButton>Click Me</DisclosureButton> <DisclosurePanel>Collapse or open this content!</DisclosurePanel> <blockquote>You miss 100% of the shots you don't take</blockquote> </Disclosure></div>
Disclosure defaultOpen
defaultOpen?: boolean
Whether or not an uncontrolled disclosure component should default to its open
state on the initial render. Defaults to false
.
Disclosure id
id?: string | number
An id used to assign aria and id attributes to nested DisclosureButton
and DisclosurePanel
components.
Since the Disclosure component itself does not render a DOM element, an id
prop will not appear in the DOM directly as may be expected. Rather, we need to generate IDs for the panel and button based on a disclosure ID for aria compliance. If no id
is passed we will generate descendant IDs for you.
<Disclosure id="awesome-disclosure"> <div> {" "} {/* no ID passed here! */} <DisclosureButton /> {/* <button id="awesome-disclosure--button" /> */} <DisclosurePanel /> {/* <div id="awesome-disclosure--panel" /> */} </div></Disclosure>
Disclosure onChange
onChange?: () => void
The callback that is fired when a disclosure's open state is changed.
Disclosure open
open?: boolean
The controlled open state of the disclosure. The open
prop should be used along with onChange
to create controlled disclosure components.
const [open, setOpen] = React.useState(false);return ( <Disclosure open={open} onChange={() => setOpen(!open)}> <DisclosureButton>I have a secret</DisclosureButton> <DisclosurePanel> Ante rhoncus facilisis iaculis nostra faucibus vehicula ac consectetur pretium, lacus nunc consequat id viverra facilisi ligula eleifend, congue gravida malesuada proin scelerisque luctus est convallis. </DisclosurePanel> </Disclosure>);
DisclosureButton
The trigger button a user clicks to interact with a disclosure.
DisclosureButton CSS Selectors
Please see the styling guide.
[data-reach-disclosure-button] {}[data-reach-disclosure-button][data-state="open"] {}[data-reach-disclosure-button][data-state="collapsed"] {}
DisclosureButton Props
DisclosureButton as
as?: keyof JSX.IntrinsicElements | React.ComponentType
A string representing an HTML element or a React component that will tell the DisclosureButton
what element to render. Defaults to button
.
NOTE: Many semantic elements, such as button
elements, have meaning to assistive devices and browsers that provide context for the user and, in many cases, provide or restrict interactive behaviors. Use caution when overriding our defaults and make sure that the element you choose to render provides the same experience for all users.
DisclosureButton children
children: React.ReactNode
Typically a text string that serves as a label for the disclosure button, though nested DOM nodes can be passed as well so long as they are valid children of interactive elements.
- Further reading: Be Wary of Nesting Roles by Adrian Roselli
DisclosurePanel
The collapsible panel in which inner content for a disclosure item is rendered.
DisclosurePanel CSS Selectors
Please see the styling guide.
[data-reach-disclosure-panel] {}[data-reach-disclosure-panel][data-state="open"] {}[data-reach-disclosure-panel][data-state="collapsed"] {}
DisclosurePanel Props
DisclosurePanel as
as?: keyof JSX.IntrinsicElements | React.ComponentType
A string representing an HTML element or a React component that will tell the DisclosurePanel
what element to render. Defaults to div
.
NOTE: Many semantic elements, such as button
elements, have meaning to assistive devices and browsers that provide context for the user and, in many cases, provide or restrict interactive behaviors. Use caution when overriding our defaults and make sure that the element you choose to render provides the same experience for all users.
DisclosurePanel children
children: React.ReactNode
Inner collapsible content for the disclosure item.
useDisclosureContext
function useDisclosureContext(): { id: string | undefined; panelId: string; open: boolean }
A hook that exposes data for a given Disclosure
component to its descendants.