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.
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 collapsibleCopies 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.jsonWorks, 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
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.
| Prop | Type | Default |
|---|---|---|
titlerequiredThe trigger content. It is also the accessible name of the trigger button. | node | none |
summaryA short line under the title that stays visible when the region is closed, e.g. a count or a status. | node | none |
defaultExpandedOpen at first when uncontrolled. | boolean | false |
isExpandedControlled open state. | boolean | none |
onExpandedChangeCalled when the region opens or closes. | (isExpanded: boolean) => void | none |
isDisabledDisables the trigger. | boolean | false |
childrenrequiredThe content that opens and closes. | node | none |
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