Skip to content

Collapsible

One region that opens and closes under a trigger, for detail most people do not need at first. For a stack of related sections, use Accordion.

Displayv0.1.0experimentalWCAG 2.2 AAView spec
import { Collapsible } from "@rdloom/react";

export default function CollapsibleBasicExample() {
  return (
    <div className="w-full max-w-md">
      <Collapsible title="Advanced options">
        <p>Retries, timeouts and the region used for this request. Most people never need to change these.</p>
      </Collapsible>
    </div>
  );
}

Installation

npx rdloom add collapsible

Copies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes. It needs react-aria-components; add --install to install them.

Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/collapsible.json

Works, but without upgrade tracking.

Usage

import { Collapsible } from "@rdloom/react";

<div className="w-full max-w-md">
  <Collapsible title="Advanced options">
    <p>Retries, timeouts and the region used for this request. Most people never need to change these.</p>
  </Collapsible>
</div>

Controlled

import { useState } from "react";
import { Button, Collapsible } from "@rdloom/react";

export default function CollapsibleControlledExample() {
  const [open, setOpen] = useState(false);
  return (
    <div className="flex w-full max-w-md flex-col gap-3">
      <Button variant="secondary" size="sm" onPress={() => setOpen((v) => !v)}>
        {open ? "Close details" : "Open details"}
      </Button>
      <Collapsible title="Delivery details" isExpanded={open} onExpandedChange={setOpen}>
        <p>Delivered by courier on weekdays between 9:00 and 17:00. Someone must be there to sign.</p>
      </Collapsible>
    </div>
  );
}

With summary line

  • src/invoice.ts
  • src/totals.ts
  • test/totals.test.ts
import { Collapsible } from "@rdloom/react";

export default function CollapsibleWithSummaryLineExample() {
  return (
    <div className="w-full max-w-md">
      <Collapsible title="Changed files" summary="3 files, 42 lines added" defaultExpanded>
        <ul className="list-disc ps-5">
          <li>src/invoice.ts</li>
          <li>src/totals.ts</li>
          <li>test/totals.test.ts</li>
        </ul>
      </Collapsible>
    </div>
  );
}

API Reference

Defined by the spec. Components also accept the props of the React Aria component they wrap.

PropTypeDefault
titlerequired

The trigger content. It is also the accessible name of the trigger button.

nodenone
summary

A short line under the title that stays visible when the region is closed, e.g. a count or a status.

nodenone
defaultExpanded

Open at first when uncontrolled.

booleanfalse
isExpanded

Controlled open state.

booleannone
onExpandedChange

Called when the region opens or closes.

(isExpanded: boolean) => voidnone
isDisabled

Disables the trigger.

booleanfalse
childrenrequired

The content that opens and closes.

nodenone

Accessibility

Role group, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.

Keyboard

  • Tab moves to the trigger
  • Enter or Space opens or closes the region

Screen readers announce

  • The trigger is announced as a button, expanded or collapsed
  • Opening it announces it as expanded; the content follows in reading order

What your code must do

  • The trigger is a button exposing aria-expanded and aria-controls
  • The region is labelled by the trigger
  • Closed content is removed from the tab order and hidden from screen readers
  • Opening and closing respect reduced motion

Guidelines

Use it when

  • A single block of optional detail: advanced options, a long note, raw output
  • A summary with a way to see more

Avoid it when

  • Several related sections: use Accordion
  • Content everyone needs: show it

Don't

  • Hiding the only way to complete a task inside a closed region
  • A title that does not say what is inside

Design tokens

The semantic tokens this component uses. Change them once and every component follows; see Design tokens.

  • --rd-color-border-default
  • --rd-color-text-default
  • --rd-color-text-muted
  • --rd-color-surface-subtle
  • --rd-color-focus-ring
  • --rd-radius-control