Skip to content
UI

Collapsible

A region of content that the user can show and hide with a trigger.

@zenoxai/ui/components/collapsibleBase UI Markdown
3 related alerts
acme-login.co
<Collapsible className="flex w-full max-w-sm flex-col gap-2">
  <div className="flex items-center justify-between gap-4">
    <span className="text-sm font-medium text-text-primary">
      3 related alerts
    </span>
    <CollapsibleTrigger
      render={
        <Button
          variant="ghost"
          size="icon-sm"
          aria-label="Toggle related alerts"
        />
      }
    >
      <ChevronsUpDownIcon />
    </CollapsibleTrigger>
  </div>
  <div className="rounded-md border border-border px-3 py-2 font-mono text-sm">
    acme-login.co
  </div>
  <CollapsibleContent className="flex flex-col gap-2">
    <div className="rounded-md border border-border px-3 py-2 font-mono text-sm">
      acme-support.net
    </div>
    <div className="rounded-md border border-border px-3 py-2 font-mono text-sm">
      acrne.com
    </div>
  </CollapsibleContent>
</Collapsible>

Usage

import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from "@zenoxai/ui/components/collapsible"
<Collapsible>
  <CollapsibleTrigger>Show related alerts</CollapsibleTrigger>
  <CollapsibleContent>...</CollapsibleContent>
</Collapsible>

Use a collapsible for one optional region: related records, advanced filters, the raw payload of an event. The trigger carries no styles, so it looks like whatever you render; style it as a Button through render. The content has no look of its own either, but its height animates open and closed with the same motion as an Accordion panel. It clips its children while it moves, so leave room for focus rings of controls placed at its edges.

For several sections in a row, use an Accordion, which also handles keyboard movement between the headings.

Examples

Controlled

Pass open and onOpenChange when other parts of the page need the state, for example to change the trigger label.

function CollapsibleControlled() {
  const [open, setOpen] = React.useState(false)

  return (
    <Collapsible
      open={open}
      onOpenChange={setOpen}
      className="flex w-full max-w-sm flex-col gap-3"
    >
      <CollapsibleTrigger
        render={<Button variant="outline" className="w-fit" />}
      >
        {open ? "Hide advanced filters" : "Show advanced filters"}
      </CollapsibleTrigger>
      <CollapsibleContent>
        <ul className="flex flex-col gap-1 rounded-md bg-surface-muted p-3 text-sm text-text-secondary">
          <li>Detection source: Domain monitoring</li>
          <li>First seen: last 30 days</li>
          <li>Tenant: Acme Corp</li>
        </ul>
      </CollapsibleContent>
    </Collapsible>
  )
}

Accessibility

  • The trigger is a button with aria-expanded and aria-controls pointing to the content. Enter and Space toggle it.
  • An icon-only trigger needs an aria-label that names the content it shows (“Toggle related alerts”).
  • The content is unmounted while closed. Set keepMounted on CollapsibleContent to keep it in the DOM, or hiddenUntilFound so find-in-page can open it.

API reference

Generated from the TypeScript source. className, style and children are accepted everywhere and omitted below.

Collapsible

Collapsible shows and hides one region with a CollapsibleTrigger, such as advanced options or the rest of a long description. For a stack of such sections, use Accordion.

PropTypeDefault
defaultOpenboolean

Whether the collapsible panel is initially open.

false
disabledboolean

Whether the component should ignore user interaction.

false
onOpenChange((open: boolean, eventDetails: CollapsibleRootChangeEventDetails) => void)

Event handler called when the panel is opened or closed.

-
openboolean

Whether the collapsible panel is currently open.

-
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, CollapsibleRootState>

Allows you to replace the component's HTML element with a different tag, or compose it with another component.

-

CollapsibleTrigger

PropTypeDefault
nativeButtonboolean

Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`).

true
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, CollapsibleTriggerState>

Allows you to replace the component's HTML element with a different tag, or compose it with another component.

-

CollapsibleContent

CollapsibleContent is the region that opens and closes. Its height animates like an AccordionContent; it clips its content while it moves.

PropTypeDefault
hiddenUntilFoundboolean

Allows the browser's built-in page search to find and expand the panel contents.

false
keepMountedboolean

Whether to keep the element in the DOM while the panel is hidden. This prop is ignored when `hiddenUntilFound` is used.

false
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, CollapsiblePanelState>

Allows you to replace the component's HTML element with a different tag, or compose it with another component.

-