Skip to content

Collapse

Collapse stacks CollapseItems: each is a header that shows or hides the content below it. The content’s height animates in CSS.

Demos

Basic

Items open and close independently. defaultExpandedNames opens some at first.

Accordion

accordion keeps at most one item open: opening one closes the others.

Arrow placement

arrowPlacement="right" puts the arrow after the title.

Controlled

expandedNames with onUpdateExpandedNames holds the open items in your state.

Header extra

headerExtra puts content at the end of the header, such as a count or a timestamp.

Custom arrow

arrow replaces the chevron. Like title and headerExtra it takes a node or a function of { collapsed }; set on the Collapse it applies to every item. A custom arrow is not rotated.

Disabled

A disabled item can’t be toggled.

Trigger areas

triggerAreas picks which parts of the header toggle on click: main (the title), arrow and extra. The header stays a button, so Enter and Space always toggle it.

Display directive

With displayDirective="if" (the default) collapsed content is unmounted once it has closed; with show it stays mounted and is only hidden, so it keeps its state.

Nested

Accessibility

Each header follows the WAI-ARIA accordion pattern: a heading (role="heading", aria-level="3") holding a native button with aria-expanded and aria-controls, and the content is a role="region" labelled by that button. Tab moves between headers and Enter or Space toggles. Collapsed content is visibility: hidden, so it is out of the tab order and the accessibility tree. With prefers-reduced-motion the content opens and closes without animating.

Collapse Props

NameTypeDefaultDescriptionVersion
accordionbooleanfalseKeeps at most one item open.Unreleased
arrowReactNode | (state: { collapsed: boolean }) => ReactNodeundefinedA custom arrow for every item.Unreleased
arrowPlacementleft | rightleftWhich side of the title the arrow sits on.Unreleased
defaultExpandedNamesstring | number | Array<string | number> | nullnullThe items open at first when uncontrolled.Unreleased
displayDirectiveif | showifif unmounts collapsed content; show keeps it mounted and hidden.Unreleased
expandedNamesstring | number | Array<string | number> | nullundefinedThe open items when controlled.Unreleased
headerExtraReactNode | (state: { collapsed: boolean }) => ReactNodeundefinedExtra content at the end of every header.Unreleased
triggerAreasArray<main | arrow | extra>['main', 'extra', 'arrow']Which parts of a header toggle on click.Unreleased
onItemHeaderClick(info: { name: string | number, expanded: boolean, event: MouseEvent }) => voidundefinedCalled when a header click toggles an item.Unreleased
onUpdateExpandedNames(names: Array<string | number>) => voidundefinedCalled with the open items when one is toggled.Unreleased

CollapseItem Props

NameTypeDefaultDescriptionVersion
namestring | numbera generated idIdentifies the item in expandedNames.Unreleased
titleReactNode | (state: { collapsed: boolean }) => ReactNodeundefinedThe header’s title.Unreleased
headerExtraReactNode | (state: { collapsed: boolean }) => ReactNodeundefinedExtra content at the end of the header; overrides the Collapse’s.Unreleased
arrowReactNode | (state: { collapsed: boolean }) => ReactNodeundefinedReplaces the chevron; overrides the Collapse’s.Unreleased
disabledbooleanfalseKeeps the item from toggling.Unreleased
displayDirectiveif | showundefinedOverrides the Collapse’s displayDirective.Unreleased

Both components also accept native div attributes and a ref. The header parts are the title, headerExtra and arrow props, and the content is children. onUpdateExpandedNames always receives an array.