Redpanda UIRedpanda UI

Collapsible

An interactive component which expands/collapses a panel.

Made by imskyleen

Installation

Loading component...

Controlled

Loading component...

Multiple independent collapsibles

Loading component...

Disabled

Loading component...

Default open

Loading component...

Chevron on leading edge

Loading component...

Reveal sensitive content

Loading component...

Usage

<Collapsible>
  <CollapsibleTrigger>Collapsible Trigger</CollapsibleTrigger>
  <CollapsibleContent>Collapsible Content</CollapsibleContent>
</Collapsible>

When to use

Use this decision tree to determine when to use the Collapsible component:

Props

Keyboard interactions

KeyAction
Enter / Space on CollapsibleTriggerToggles the panel open / closed.
TabMoves focus to the next focusable element (including into the panel when open).

Accessibility

  • The trigger exposes aria-expanded + aria-controls pointing at the panel; Base UI also sets the compat data-state="open" | "closed" attribute so existing CSS selectors keep working.
  • The trigger must be a real button (or another focusable element via asChild); static <div> triggers lose keyboard activation.
  • Use keepMounted on CollapsibleContent when the hidden content must remain in the DOM for SEO, intersection observers, or mid-animation measurements. See MIGRATION.mdforceMount from Radix is no longer forwarded.

Controlled vs uncontrolled

Uncontrolled — trigger toggles the panel locally:

<Collapsible>
  <CollapsibleTrigger>Toggle</CollapsibleTrigger>
  <CollapsibleContent>{/* ... */}</CollapsibleContent>
</Collapsible>

Controlled — drive open from parent state (e.g. expand all / collapse all from a toolbar):

const [open, setOpen] = useState(false);

<Collapsible open={open} onOpenChange={setOpen}>
  <CollapsibleTrigger>Toggle</CollapsibleTrigger>
  <CollapsibleContent>{/* ... */}</CollapsibleContent>
</Collapsible>

Animate UI Props

CollapsibleContent

Prop

Type

Don't delete from the DOM

The choice made (also Base UI's default) is to remove the element from the DOM for accessibility and performance reasons. However, this may pose a problem for SEO. If you want your Collapsible content to be taken into account by Google, replace the CollapsibleContent component with:

components/animate-ui/collapsible.tsx
const CollapsibleContent = React.forwardRef<
  React.ElementRef<typeof CollapsiblePrimitive.Content>,
  CollapsibleContentProps
>(
  (
    {
      className,
      children,
      transition = { type: 'spring', stiffness: 150, damping: 17 },
      ...props
    },
    ref,
  ) => {
    const { isOpen } = useCollapsible();

    return (
      <CollapsiblePrimitive.Content asChild forceMount ref={ref} {...props}>
        <motion.div
          layout
          initial={false}
          animate={
            isOpen
              ? { opacity: 1, height: 'auto', overflow: 'hidden' }
              : { opacity: 0, height: 0, overflow: 'hidden' }
          }
          transition={transition}
          className={className}
        >
          {children}
        </motion.div>
      </CollapsiblePrimitive.Content>
    );
  },
);

Credits

Recent changes

  • patchv1.2.0Pin shipped dependency floors to the version we develop against. Registry items now declare ranges like `^5.1.9` (the actual installed version) instead of collapsing to `^5.0.0`, so consumers start on the known-tested b…#133
  • minorv1.1.0Theme docs refresh, readability pass on semantic foregrounds, and consumer-facing Base UI regression fixes.#121
  • minorv1.0.0Post-Base-UI polish. Public API unchanged.#116
  • majorv1.0.0Migrate every Radix-based primitive to `@base-ui/react@^1.4.0` (Base UI).#114
  • patchv0.3.1**Accordion** - `AccordionTrigger` now shows `cursor-pointer` on hover.#112
See full history →
Built by malinskibeniamin. The source code is available on GitHub.

On this page