React hook for easily creating accessible collapsed content.
- Written in TypeScript
- Handles all of the accessibility props, so you can focus on styling
- Flexibility - not tied to any single animation pattern, you control how (or if) it animates.
- Nested collapsible content areas
- Controlled component, gives you state and a setter, and lets you handle the rest.
npm i react-usecollapsible
Try it out on CodeSandbox
import { useCollapsible } from 'react-usecollapsible';
const Collapsible = () => {
const { triggerProps, contentProps } = useCollapsible();
return (
<>
<button {...triggerProps}>Toggle</button>
<div {...contentProps}>Collapsible content</div>
</>
);
};
import { useCollapsible } from 'react-usecollapsible';
const Collapsible = () => {
const { triggerProps, contentProps } = useCollapsible({
defaultExpanded: true,
});
return (
<>
<button {...triggerProps}>Toggle</button>
<div {...contentProps}>Collapsible content</div>
</>
);
};
import { useCollapsible } from 'react-usecollapsible';
const Collapsible = () => {
const { expanded, setExpanded, triggerProps, contentProps } = useCollapsible();
return (
<>
<button {...triggerProps} onClick={() => setExpanded((e) => !e)}>
{expanded ? 'Hide' : 'Show'}
</button>
<div {...contentProps} style={{ display: expanded ? 'block' : 'none' }}>
Collapsible content
</div>
</>
);
};
import { useCollapsible } from 'react-usecollapsible';
const Collapsible = () => {
const { expanded, setExpanded, triggerProps, contentProps } = useCollapsible({
id: 'my_custom_id',
});
// contentProps.id and triggerProps['aria-controls'] will be 'my_custom_id'
return (
<>
<button {...triggerProps}>Toggle</button>
<div {...contentProps}>Collapsible content</div>
</>
);
};
Property | Type | Default | Description |
---|---|---|---|
defaultExpanded | boolean | false | Initial state of the collapsible content |
id | string | useId() hook response |
Unique ID for connecting the trigger to content |
Property | Type | Description |
---|---|---|
expanded | boolean | useState value for expansion of content |
setExpanded | React.Dispatch<React.SetStateAction> | useState setter for expansion of content |
triggerProps | TriggerProps | Props to be applied to content visibility trigger |
contentProps | ContentProps | Props to be applied to content area |
Why isn't my content area hiding or showing when I toggle the state?
This is likely because you need to style your content based on the expanded state. To give maximum flexibility in how you'd like to animate (or not animate) the expansion, styling is left completely up to you.
This hook controls how accessibility tools see the content, not how it looks visually.
Will you ever expand this to add animations?
Not likely. This is purposefully simplified to only control the accessibility properties of collapsible content.
Feel free to use this hook as a dependency on a component package that implements animations if you'd like!