VIII Wayfinding

Star on GitHubFeedback
VIII WayfindingNative HTMLot-disclose

Accordion

Questions you open. Ruled off, with a plus that winds into a cross as the question swells into a heading; or run in with their answers like a book's paragraphs; glossed in the outer column; or stood side by side as columns that widen.

Report an issue with Accordion

Example

cross
How long does a project take?

Most identity work runs four to eight weeks, and websites take a season. We agree the timeline before anything starts, and we keep to it.

Do you work with early teams?

Often. Some of the best briefs arrive before there's a name.

What do you need from us to begin?

A short brief, one person who can decide, and an hour for a first call.

run-in
How long does a project take?

Most identity work runs four to eight weeks, and websites take a season. We agree the timeline before anything starts, and we keep to it.

Do you work with early teams?

Often. Some of the best briefs arrive before there's a name.

What do you need from us to begin?

A short brief, one person who can decide, and an hour for a first call.

gloss
How long does a project take?

Most identity work runs four to eight weeks, and websites take a season. We agree the timeline before anything starts, and we keep to it.

Do you work with early teams?

Often. Some of the best briefs arrive before there's a name.

What do you need from us to begin?

A short brief, one person who can decide, and an hour for a first call.

horizontal
Identity for a ferry line

Keep the flag, lose the anchor. The timetable is the real product, so the type is chosen for the quay, read from twenty metres in the rain.

A reading room

Shelving, signs and a catalogue for a library that opens at night. Every sign is set in one size, so nothing shouts.

Wine labels

Six labels, one grid. The vintage stands large; the grape is set in the italic, because the grower chose it.

The annual report

Forty pages of figures set as type, with nothing drawn.

cross, closed
Do you work with early teams?

Often, before there's a name.

cross, open
Do you work with early teams?

Often, before there's a name.

run-in, closed
Do you work with early teams?

Often, before there's a name.

run-in, pointed at
Do you work with early teams?

Often, before there's a name.

run-in, open
Do you work with early teams?

Often, before there's a name.

gloss, closed
Do you work with early teams?

Often, before there's a name.

gloss, open
Do you work with early teams?

Often, before there's a name.

horizontal, one open, one pointed at
A reading room

Every sign is set in one size.

Wine labels

Six labels, one grid.

Install

Run it in a project that has the shadcn CLI set up. It brings the 0nlyType base along.

npx shadcn@latest add https://thedirectors.agency/ui/r/accordion.json

Usage

accordion-example.tsx
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, type AccordionProps } from "@/components/ui/accordion"const FAQ = [["How long does a project take?", "Most identity work runs four to eight weeks, and websites take a season. We agree the timeline before anything starts, and we keep to it."],["Do you work with early teams?", "Often. Some of the best briefs arrive before there's a name."],["What do you need from us to begin?", "A short brief, one person who can decide, and an hour for a first call."],]function Questions({ variant }: { variant: AccordionProps["variant"] }) {return (<Accordion type="single" variant={variant}>{FAQ.map(([q, a], i) => (<AccordionItem key={q} defaultOpen={i === 0}><AccordionTrigger>{q}</AccordionTrigger><AccordionContent><p>{a}</p></AccordionContent></AccordionItem>))}</Accordion>)}const WORK = [["Identity for a ferry line", "Keep the flag, lose the anchor. The timetable is the real product, so the type is chosen for the quay, read from twenty metres in the rain."],["A reading room", "Shelving, signs and a catalogue for a library that opens at night. Every sign is set in one size, so nothing shouts."],["Wine labels", "Six labels, one grid. The vintage stands large; the grape is set in the italic, because the grower chose it."],["The annual report", "Forty pages of figures set as type, with nothing drawn."],]function Columns() {return (<Accordion type="single" orientation="horizontal">{WORK.map(([q, a], i) => (<AccordionItem key={q} defaultOpen={i === 0}><AccordionTrigger>{q}</AccordionTrigger><AccordionContent><p>{a}</p></AccordionContent></AccordionItem>))}</Accordion>)}export default function Example() {return (<div className="grid gap-y-10">{(["cross", "run-in", "gloss"] as const).map((v) => (<div key={v} className="grid gap-y-4"><span className="ot-label">{v}</span><Questions variant={v} /></div>))}<div className="grid gap-y-4"><span className="ot-label">horizontal</span><Columns /></div></div>)}

Contract

  • Underneath: native <details>.
  • Anatomy: <div class="ot-accordion" data-variant="cross | run-in | gloss" data-orientation="horizontal"> holding <details class="ot-disclose"><summary>Question</summary><div class="ot-disclose-body">…</div></details> for each question.
  • cross (the default): questions ruled off. The + winds 45° into × with spiccato, and the question exhales as it opens: it swells a fifth, from mp to mf, and goes wide and light (width 112%, weight 300), so the open question becomes the heading of its answer, as the big words of "Less is more." stand over their note. The + keeps its size. The content opens by animating block-size (::details-content) over --ot-andante, and the answer settles into the space.
  • run-in: the book's run-in head. No rules; the questions are paragraphs held apart by space. Each question is set heavy (600) and floats at the start of its own line; closed, a pencil ellipsis trails after it (pointing inks it). Open, the ellipsis goes and the answer runs on from the question on the same line, light (300) in graphite, as one paragraph; it is written in line by line from the question, a steep soft-edged wipe that steps down a line as it crosses one (mirrored right to left). Held to the measure; p size below 40rem. Forced colours drop the wipe.
  • gloss: the answer is hung beside its question in the outer column (3 : 2), flush to the outer edge and ragged toward the question, the way a sidenote glosses the line it stands by (the notes of "Less is more." and "the silence that heals"). Space holds the columns apart; no rule stands between. The question keeps its size and exhales only in width and weight. Open, the gloss arrives from the question's side (mirrored right to left). Below 40rem it drops under the question, indented a quarter.
  • horizontal (orientation="horizontal", data-orientation): after "Healthy habits", its notes stacked a word to a line in narrow ragged columns, and the hairline grid of "Less is more.". The questions stand side by side as columns of space-9 between hairlines, each name stacked a word to a line; the open one widens (flex-grow over --ot-andante, exhale) and its name steps up from the stack onto one line as it exhales into the heading of its answer (mf, wide and light); the answer arrives once the column has made room. Closed columns keep their width, so the row ends in silence. It has its own form, so data-variant is not set and the + is set aside: the column says it opens. Below 40rem the columns stack under hairlines and the + returns.
  • Keyboard: native (Enter or Space on the summary). Single opens one at a time through the native name attribute. Horizontal: Left and Right walk the columns (mirrored right to left), Home and End go to the ends.

Props

Props of Accordion
PropTypeDefaultWhat it does
type"single" | "multiple""multiple"On Accordion. Single opens one item at a time, using the native name attribute on its details elements.
variant"cross" | "run-in" | "gloss""cross"On Accordion. cross: questions ruled off; the + winds into × and the open question swells a fifth into the heading of its answer. run-in: the book's run-in head; no rules, the question set heavy with an ellipsis trailing it, and opened, the answer runs on along the same line, written outward from the question. gloss: the answer is hung beside its question in the outer column, flush to the outer edge, as a sidenote glosses a line; below 40rem it drops under the question.
orientation"vertical" | "horizontal""vertical"On Accordion. horizontal: the questions stand side by side as narrow columns between hairlines, each name stacked a word to a line; the open one widens and its name steps up onto one line over its answer, which arrives once the column has made room. Left and Right walk the columns (mirrored right to left), Home and End go to the ends. The variant is set aside; below 40rem the columns stack.
AccordionItemdetailsOne question and its answer. Accepts the details props, such as onToggle.
AccordionItem.defaultOpenbooleanfalseStart open. The browser keeps the state afterwards.
AccordionTriggersummaryThe question. Native, so Enter and Space open it.
AccordionContentdivThe answer, held to a readable measure.

Craft

Where its move comes from

Where its move comes from
ComponentReferenceMove
DisclosureThe overture; "Less is more."The question exhales and swells into the heading of its answer
Disclosure, run-inThe book's run-in headThe answer runs on from the question, in one paragraph
Disclosure, glossThe sidenote; "Less is more." notesThe answer hung beside its question in the outer column
Disclosure, horizontal"Healthy habits" narrow columns; "Less is more." hairline gridThe open column widens and its name steps up from a stack onto one line

How it moves

How it moves
ComponentArticulationWhat moves
DisclosureSpiccatoThe cross winds past; the question swells; the answer settles
Disclosure, run-inWrittenThe ellipsis goes and the answer is written on from the question, line by line
Disclosure, glossAsideThe gloss arrives from the question's side
Disclosure, horizontalWidenThe column widens and the name re-sets onto one line; the answer arrives once there's room