IX Surfaces

Star on GitHubFeedback
IX SurfacesNative HTMLot-card

Card

A column under a rule, not a box. Point at it and an ink stroke passes along the rule.

Report an issue with Card

Example

Identity

Names, marks, and the rules that keep them from drifting.

Three projectsFrom six weeks

Websites

Built to be read slowly and used for years, then handed over.

Three projectsA season

Motion

Titles and idents: things that move once, and mean it.

One projectFour weeks

“They took our name away for a month and gave it back with a spine.”

Ines Halden, founder

Halden, an identity

A website, in pounds

Fixed before we start, paid in three parts.

Discovery
2,400
Design
9,600
Handover
1,200
Total
13,200
Rest

Identity

Names and marks.

Pointed at

Identity

Names and marks.

epigraph, rest

“It gave us back our name.”

Ines Halden

Halden

epigraph, pointed at

“It gave us back our name.”

Ines Halden

Halden

ledger, rest

A website

Design
9,600
Handover
1,200
Total
10,800
ledger, pointed at

A website

Design
9,600
Handover
1,200
Total
10,800

Install

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

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

Usage

card-example.tsx
import { Card, CardDescription, CardFigure, CardFooter, CardLink, CardSum, CardTitle } from "@/components/ui/card"const services = [{ letter: "I", name: "Identity", body: "Names, marks, and the rules that keep them from drifting.", facts: ["Three projects", "From six weeks"] },{ letter: "W", name: "Websites", body: "Built to be read slowly and used for years, then handed over.", facts: ["Three projects", "A season"] },{ letter: "M", name: "Motion", body: "Titles and idents: things that move once, and mean it.", facts: ["One project", "Four weeks"] },]const fee = [["Discovery", "2,400"],["Design", "9,600"],["Handover", "1,200"],["Total", "13,200"],]export default function Example() {return (<div className="grid gap-y-16"><div className="grid gap-x-10 gap-y-12 sm:grid-cols-3">{services.map((s) => (<Card key={s.name}><CardFigure>{s.letter}</CardFigure><CardTitle><CardLink href="#card">{s.name}</CardLink></CardTitle><CardDescription>{s.body}</CardDescription><CardFooter>{s.facts.map((f) => (<span key={f}>{f}</span>))}</CardFooter></Card>))}</div><div className="grid gap-x-10 gap-y-12 sm:grid-cols-2"><Card variant="epigraph"><CardDescription>“They took our name away for a month and gave it back with a spine.”</CardDescription><CardFooter><span>Ines Halden, founder</span></CardFooter><CardTitle><CardLink href="#card">Halden, an identity</CardLink></CardTitle></Card><Card variant="ledger"><CardTitle><CardLink href="#card">A website, in pounds</CardLink></CardTitle><CardDescription>Fixed before we start, paid in three parts.</CardDescription><CardSum>{fee.map(([what, sum]) => (<div key={what}><dt>{what}</dt><dd>{sum}</dd></div>))}</CardSum></Card></div></div>)}

Contract

  • Underneath: native.
  • Anatomy: <article class="ot-card" data-variant="rule | epigraph | ledger"> holding an optional .ot-card-figure (one giant letter, aria-hidden), .ot-card-title with .ot-card-link, .ot-card-body, .ot-card-foot, and for the ledger <dl class="ot-card-sum"> (a <div> of <dt> and <dd> per line, the last the total).
  • A column under a rule, not a box. The giant letter hangs from the rule with its top cut off by it, the way SPECTRA's line cuts its word, so the stroke that passes along the rule when you point at the card passes over the cut. The link's hit area covers the card; focus rings the whole card in the accent.
  • Epigraph: someone else's words about the work, set before its name the way a book sets a quotation before a chapter. The quotation stands first, indented to the end of the column, in the expression italic (italic here by the book's convention for epigraphs, like .ot-term, not because the reader typed it), its attribution flush to the end after a short rule, as the em dash would stand. The rule leaves the top of the card and opens the title below instead, like a chapter's head, and pointing passes the stroke along it there.
  • Ledger: for what something costs. The lines of .ot-card-sum add up in tabular figures, in a column as wide as the total; the total, large and light, is ruled off the way an account is, a single rule over it and a double rule under it, both only as wide as the figures. Nothing else changes: it keeps the rule and its stroke.
  • Forced colours: the rule becomes a border, since background images are dropped.

Props

Props of Card
PropTypeDefaultWhat it does
variant"rule" | "epigraph" | "ledger""rule"rule: a column under a rule, the giant letter hanging from it with its top cut off, the way SPECTRA's line cuts its word. epigraph: for someone else's words about the work; the quotation stands first, indented to the end of the column in the italic a book gives an epigraph, with its attribution after a short rule, and the rule moves down to open the title like a chapter's head. ledger: for what something costs; CardSum's figures add up in a column as wide as the total, which is ruled off the way an account is, a single rule over it and a double rule under it.
CardFigurepOne giant letter, cropped by the rule like a poster's headline. Decorative, so it's hidden from screen readers.
CardLinkaGoes inside CardTitle. Its hit area stretches over the whole card, so the card is a single target with one focus ring.
CardSumdlFor ledger: a <div> of <dt> and <dd> per line, the last one the total. The figures are tabular, so the column adds up by eye.
CardFooterdivA frame row: each child is a small fact, with a hairline between them.
CardLink asChildbooleanfalseLend the stretched link and focus treatment to a single child link, such as your router's Link.

Craft

Where its move comes from

Where its move comes from
ComponentReferenceMove
CardSPECTRA cropA giant letter hanging from the rule, cut off by it
Epigraph cardA book's epigraphTheir words before the name, indented to the end, the rule opening the title
Ledger cardThe accountant's ruled-off totalA single rule over the total and a double rule under it

How it moves

How it moves
ComponentArticulationWhat moves
CardPass-throughAn ink stroke passes along the rule, over the letter's cut
Epigraph cardPass-throughThe stroke passes along the rule over the title