Collapsible

Collapsible is a component that shows or hides content.

Give FeedbackWAI-ARIABundle Size

This is the collapsed content. The element that shows and hides the content has role button

When the content is visible, the element with role `button` has `aria-expanded` set to `true`

When the content panel is hidden, it is set to `false`

Installation

Base UI components are all available as a single package.

npm install @base-ui-components/react

Once you have the package installed, import the component.

import { Collapsible } from '@base-ui-components/react/Collapsible';

Anatomy

<Collapsible.Root>
  <Collapsible.Trigger>Toggle</Collapsible.Trigger>
  <Collapsible.Panel>This is the content</Collapsible.Panel>
</Collapsible.Root>

Hidden state

<Collapsible.Panel /> is unmounted from the DOM by default when the component is closed. You can use the keepMounted prop to to keep it mounted when closed, and instead rely on the hidden attribute to hide the content:

<Collapsible.Root>
  <Collapsible.Trigger>Toggle</Collapsible.Trigger>
  <Collapsible.Panel keepMounted>{/* content */}</Collapsible.Panel>
</Collapsible.Root>

Improving searchability of hidden content

This is not yet supported in Safari and Firefox as of August 2024 and will fall back to the default hidden behavior.

Content hidden in the Collapsible.Panel component can be made accessible only to a browser's find-in-page functionality with the hiddenUntilFound prop to improve searchability:

<Collapsible.Root>
  <Collapsible.Trigger>Toggle</Collapsible.Trigger>
  <Collapsible.Panel hiddenUntilFound>
    When this component is closed, this sentence will only be accessible to the browser's native
    find-in-page functionality
  </Collapsible.Panel>
</Collapsible.Root>

When hiddenUntilFound is used, the Panel remains mounted even when closed, overriding the keepMounted prop.

We recommend using CSS animations for animated collapsibles that use this feature. Currently there is browser bug that does not highlight the found text inside elements that have a CSS transition applied.

Animations

Animation states

Three states are available as data attributes to animate the Collapsible:

The component can be animate when opening or closing using either:

Styling

The Collapsible.Panel element receives the following CSS variables about its dimensions, which can be used to style animations or transitions:

CSS Animations

CSS animations can be used with two declarations:

.CollapsiblePanel {
  overflow: hidden;
  animation: slideUp 300ms ease-in;
}

.CollapsiblePanel[data-open] {
  animation: slideDown 300ms ease-out;
}

@keyframes slideDown {
  from {
    height: 0;
  }
  to {
    height: var(--collapsible-panel-height);
  }
}

@keyframes slideUp {
  from {
    height: var(--collapsible-panel-height);
  }
  to {
    height: 0;
  }
}

This is the collapsed content

You can find the Base UI repository here

This is a longer sentence and also the third paragraph

CSS Transitions

When using CSS transitions, styles for the Panel must be applied to three states:

.CollapsiblePanel {
  overflow: hidden;
  /* The final styles once closed/exited  */
  height: 0;
  transition: height 300ms ease-in;
}

/* The final styles once opened/entered */
.CollapsiblePanel[data-open] {
  height: var(--collapsible-panel-height);
  transition: height 300ms ease-out;
}

/* The initial styles when opening/entering */
.CollapsiblePanel[data-entering] {
  height: 0;
}

This is the collapsed content.

You can find the Base UI repository here.

This is a longer sentence and also the third paragraph.

JavaScript Animations

Use the keepMounted prop lets an external library control the mounting, for example framer-motion:

function App() {
  const [open, setOpen] = useState(false);
  return (
    <Collapsible.Root open={open} onOpenChange={setOpen}>
      <Collapsible.Trigger>Toggle</Collapsible.Trigger>
      <Collapsible.Panel
        keepMounted
        render={
          <motion.div
            key="MyAnimatedCollapsiblePanel"
            initial={false}
            animate={open ? 'open' : 'closed'}
            exit={!open ? 'open' : 'closed'}
            variants={{
              open: {
                height: 'auto',
                transition: { duration: 0.6, ease: 'ease-out' },
              },
              closed: {
                height: 0,
                transition: { duration: 0.6, ease: 'ease-in' },
                transitionEnd: { display: 'revert-layer' },
              },
            }}
          />
        }
      >
        This is the content
      </Collapsible.Panel>
    </Collapsible.Root>
  );
}

Overriding default components

Use the render prop to override the rendered elements with your own components. The Collapsible.Root component does not render an element to the DOM by default, but can do so with the render prop:

// Element shorthand
<Collapsible.Root render={<MyCollapsibleRoot />} />
// Function
<Collapsible.Root render={(props) => <MyCollapsibleRoot {...props} />} />

API Reference

CollapsibleRoot

PropTypeDefaultDescription
animatedbooltrueIf true, the component supports CSS/JS-based animations and transitions.
classNameunionClass names applied to the element or a function that returns them based on the component's state.
defaultOpenbooltrueIf true, the Collapsible is initially open. This is the uncontrolled counterpart of open.
disabledboolfalseIf true, the component is disabled.
onOpenChangefuncCallback fired when the Collapsible is opened or closed.
openboolIf true, the Collapsible is initially open. This is the controlled counterpart of defaultOpen.
renderunionA function to customize rendering of the component.

CollapsibleTrigger

PropTypeDefaultDescription
classNameunionClass names applied to the element or a function that returns them based on the component's state.
renderunionA function to customize rendering of the component.

CollapsiblePanel

PropTypeDefaultDescription
classNameunionClass names applied to the element or a function that returns them based on the component's state.
hiddenUntilFoundboolfalseIf true, sets the hidden state using hidden="until-found". The panel remains mounted in the DOM when closed and overrides keepMounted. If false, sets the hidden state using hidden.
keepMountedboolfalseIf true, the panel remains mounted when closed and is instead hidden using the hidden attribute If false, the panel is unmounted when closed. If the hiddenUntilFound prop is used, the panel overrides this prop and is remains mounted when closed.
renderunionA function to customize rendering of the component.

Contents