Starter Docs
UI

Collapsible

A native details element that opens to its own height, fades its content in out of a blur and turns its chevron over. Controlled or not, and opened by find in page. Every animation is CSS.

More details
Keep extra information tucked away until someone needs it. Find in page opens it.

Installation

Add the registry to components.json, once

components.json
{
  "registries": {
    "@rabtx": "http://localhost:3002/r/{name}.json"
  }
}

Add the component

npx shadcn@latest add @rabtx/collapsible

Or, without the namespace, by URL:

npx shadcn@latest add http://localhost:3002/r/collapsible.json

The files land in your components/ui and are styled by your own theme. Add --overwrite to replace a shadcn component with the same name.

Usage

Installed from the registry, import from @/components/ui/collapsible; inside this monorepo, from @rabtx/ui/collapsible.

import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@rabtx/ui/collapsible";

export function Details() {
  return (
    <Collapsible>
      <CollapsibleTrigger>More details</CollapsibleTrigger>
      <CollapsibleContent>Kept out of the way until someone needs it.</CollapsibleContent>
    </Collapsible>
  );
}

It is a <details> and the trigger its <summary>: the trigger must be the first child, and everything after it folds. It opens and closes before hydration and with no script at all. The trigger draws a chevron; pass chevron={false} to leave it out. Put vertical padding inside the content (or on its children) rather than as a margin outside, so it folds with the rest.

Controlled

open and onOpenChange control it. A press, find in page or a link to text inside it all ask through onOpenChange; the element stays as open says until you pass the new value. useCollapsible() gives custom parts inside it the state and a toggle.

Starred repositoriesShow 3
rabtx/ui
rabtx/docs
rabtx/web

Closed

API

Collapsible takes everything a details takes, plus:

Prop

Type

CollapsibleTrigger takes everything a summary takes, plus chevron (default true). CollapsibleContent takes everything a div takes.

Outside React, collapsibleParts from @rabtx/ui/collapsible/styles names the classes:

<details class="rx-collapsible">
  <summary class="rx-collapsible-trigger">
    More details <span class="rx-collapsible-chevron" aria-hidden="true"></span>
  </summary>
  <div class="rx-collapsible-content">…</div>
</details>

How the motion works

The same as the Accordion, on the glide spring both ways (360 / 32 / 0.6, no overshoot, about 420ms). --_open-ease / --_open-time and --_close-ease / --_close-time on .rx-collapsible choose the springs; the Accordion sets its bouncier open there.

Accessibility

  • The <summary> is a button with its expanded state, toggled by Enter and Space.
  • Closed content is out of the accessibility tree and the Tab order.
  • A disabled collapsible's trigger has aria-disabled and tabindex="-1".
  • With reduced motion nothing grows, turns or blurs; with data-motion="off" it changes at once.

On this page