Collapsible
A list that ends in the rest of itself: the words "and 4 more" are the control.
Report an issue with CollapsibleExample
- Halden
- Northlight
- Oda Studio
and 4 moreHide these 4
- Tidewater
- Marram
- Quiet Hours
- Felt & Field
- Halden
- Northlight
- Oda Studio
TidewaterHide these 4
- Marram
- Quiet Hours
- Felt & Field
- Halden
- Northlight
- Oda Studio
Show these 4 in fullSet them small again
- Tidewater
- Marram
- Quiet Hours
- Felt & Field
Closed
- Halden
- Northlight
and 4 moreHide these 4
- Tidewater
- Marram
- Quiet Hours
- Felt & Field
Pointed at
- Halden
- Northlight
and 4 moreand 4 more
- Tidewater
- Marram
- Quiet Hours
- Felt & Field
Open
- Halden
- Northlight
and 4 moreHide these 4
- Tidewater
- Marram
- Quiet Hours
- Felt & Field
catchword, closed
- Halden
- Northlight
TidewaterHide these 4
- Marram
- Quiet Hours
- Felt & Field
catchword, pointed at
- Halden
- Northlight
TidewaterTidewater
- Marram
- Quiet Hours
- Felt & Field
catchword, open
- Halden
- Northlight
TidewaterHide these 4
- Marram
- Quiet Hours
- Felt & Field
sotto, closed
- Halden
- Northlight
Show these 4 in fullSet them small again
- Tidewater
- Marram
- Quiet Hours
- Felt & Field
sotto, pointed at
- Halden
- Northlight
Show these 4 in fullShow these 4 in full
- Tidewater
- Marram
- Quiet Hours
- Felt & Field
sotto, open
- Halden
- Northlight
Show these 4 in fullSet them small again
- Tidewater
- Marram
- Quiet Hours
- Felt & Field
Install
Run it in a project that has the shadcn CLI set up. It brings the 0nlyType base and button along.
npx shadcn@latest add https:// thedirectors.agency/ ui/ r/collapsible.jsonUsage
import type { ComponentProps } from "react"import {Collapsible,CollapsibleContent,CollapsibleList,CollapsibleTrigger,} from "@/components/ui/collapsible"const shown = ["Halden", "Northlight", "Oda Studio"]const rest = ["Tidewater", "Marram", "Quiet Hours", "Felt & Field"]function Rows({ names }: { names: string[] }) {return (<CollapsibleList>{names.map((n) => (<li key={n}>{n}</li>))}</CollapsibleList>)}function Tail(props: ComponentProps<typeof Collapsible>) {return (<Collapsible {...props}><CollapsibleTrigger openLabel="Hide these 4">and 4 more</CollapsibleTrigger><CollapsibleContent><Rows names={rest} /></CollapsibleContent></Collapsible>)}/** The catchword is the first of the rest; the content holds the others. */function Catchword(props: ComponentProps<typeof Collapsible>) {return (<Collapsible variant="catchword" {...props}><CollapsibleTrigger aria-label="Show 4 more, from Tidewater" openLabel="Hide these 4">{rest[0]}</CollapsibleTrigger><CollapsibleContent><Rows names={rest.slice(1)} /></CollapsibleContent></Collapsible>)}function Sotto(props: ComponentProps<typeof Collapsible>) {return (<Collapsible variant="sotto" {...props}><CollapsibleTrigger openLabel="Set them small again">Show these 4 in full</CollapsibleTrigger><CollapsibleContent><Rows names={rest} /></CollapsibleContent></Collapsible>)}export default function Example() {return (<div className="grid gap-x-10 gap-y-12 md:grid-cols-3" style={{ maxWidth: "60rem" }}>{[Tail, Catchword, Sotto].map((Part, i) => (<div key={i}><Rows names={shown} /><Part /></div>))}</div>)}Contract
- Underneath: native
<details>. - Anatomy:
<details class="ot-collapse">whose<summary>is the tail of a list ("and 4 more"), then.ot-collapse-list. - A list that ends in the rest of itself. The rest opens at reading speed through
::details-content, and its lines arrive in turn. - Keyboard: native.
- Variants go on
data-variant(Collapsible variant): tail (the default), catchword, sotto. Tail's words are set as the list's caption, pp, straight under the last rule. Catchword and sotto set their summary as.ot-collapse-cuewith two spans (the words, thenopenLabel). - Catchword, after the printer's catchword: the first name of the rest waits at the foot, flush to the far edge, as the next page's first word waits under the last line. Opening, it steps back to the start (the summary is a container, so it travels
100cqiless its own width) and grows into the first row of the rest, which follow it. Give the summary anaria-labelthat says what it does ("Show 4 more, from Tidewater"). - Sotto, after SPECTRA's fine print and the score's sotto voce: the rest is never hidden, only said under the breath, as one run of pp pencil fine print; the whole run is the control and inks when pointed at. Opening says it in full: each name grows into its own row, in turn, and the words to set it small again follow. The summary lies over the run in the same grid cell; its words are visually hidden while closed.
- Reduced motion: it opens at once. Right-to-left: the catchword waits at the left. Forced colours: rules and text keep their system colours.
Props
| Prop | Type | Default | What it does |
|---|---|---|---|
Collapsible | details | Holds the control and the rest. Put the rows that always show before it. | |
Collapsible.variant | "tail" | "catchword" | "sotto" | "tail" | How the list says there is more. tail: the words "and 4 more" are the control, set as a caption straight under the last rule. catchword: the first name of the rest waits at the foot, flush to the far edge, as a printer set the next page's first word under the last line; opening, it steps back to the start and becomes the first row, and the rest follow. Its label is that name, so give the trigger an aria-label ("Show 4 more, from Tidewater") and put the other names in the content. sotto: the rest is never hidden, only said under the breath, as one line of fine print in pencil that is itself the control; opening says each name in full, in turn. The trigger's words are read aloud, not shown. |
CollapsibleTrigger | summary | The control, set as a quiet Button. Its label is what the closed state says (and 4 more). | |
CollapsibleTrigger.openLabel | ReactNode | What it says once open (Hide these 4). Defaults to the closed words. | |
CollapsibleContent | div | The rest. It opens at the speed of reading. | |
CollapsibleList | ul | Rows ruled off with hairlines; inside the content, its rows arrive in turn as it opens. |
Craft
Where its move comes from
| Component | Reference | Move |
|---|---|---|
| Collapsible | "the silence that heals" captions | "and 4 more" is the control |
| Catchword collapsible | The printer's catchword | The rest's first name waits at the foot, then steps up into its row |
| Sotto collapsible | SPECTRA's fine print; the score's sotto voce | The rest is said small, never hidden; opening says it in full |
How it moves
| Component | Articulation | What moves |
|---|---|---|
| Collapsible | Arpeggio | The rest opens at reading speed, line by line |
| Catchword collapsible | Arpeggio | The catchword steps back to the start and grows; the rows follow in turn |
| Sotto collapsible | Crescendo | Each name grows from fine print into its row, in turn |