Picks
A list of choices that carry their own content. The one you took turns italic, and either a dot slides to it along a plucked string its initial hangs in the margin like a rubricated capital, its name lies faint behind the list, or two registration crosses mark its corners.
Report an issue with PicksExample
Pizzicato
Pointed at
Focus
Chosen
Disabled
Rubric
Pointed at
Chosen
No capitals
Disabled
Watermark
Register
Pointed at
Chosen
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/picks.jsonUsage
import { Pick, PickDescription, Picks, PickTitle } from "@/components/ui/picks"export default function Example() {return (<div className="grid items-start gap-x-(--ot-space-8) gap-y-(--ot-space-7) md:grid-cols-2"><Picks legend="Pair" defaultValue="press"><Pick value="parma"><PickTitle>Parma</PickTitle><PickDescription>The house pair. Sharp and bright; Bodoni cut his types in Parma.</PickDescription></Pick><Pick value="press"><PickTitle>Press</PickTitle><PickDescription>Both made for reading news on screens. Plain, warm, unhurried.</PickDescription></Pick><Pick value="paris"><PickTitle>Paris</PickTitle><PickDescription>A narrow modern voice answered in the oldest italic here.</PickDescription></Pick><Pick value="salon"><PickTitle>Salon</PickTitle><PickDescription>A grotesque with a little ink trap, and a Garamond cut for display.</PickDescription></Pick></Picks><Picks variant="rubric" legend="Ink" defaultValue="vermilion"><Pick value="lamp"><PickTitle>Lamp black</PickTitle><PickDescription>Soot from an oil lamp, ground into varnish.</PickDescription></Pick><Pick value="vermilion"><PickTitle>Vermilion</PickTitle><PickDescription>The rubricator’s red, ground from cinnabar.</PickDescription></Pick><Pick value="gall"><PickTitle>Iron gall</PickTitle><PickDescription>Brown-black, and it bites into the page for good.</PickDescription></Pick></Picks><Picks variant="watermark" legend="Paper" defaultValue="wove"><Pick value="laid"><PickTitle>Laid</PickTitle><PickDescription>Ribbed with the wires of the mould it was made on.</PickDescription></Pick><Pick value="wove"><PickTitle>Wove</PickTitle><PickDescription>Smooth as a page can be. Baskerville asked for it.</PickDescription></Pick><Pick value="cotton"><PickTitle>Cotton</PickTitle><PickDescription>Soft and heavy in the hand, and it outlasts us.</PickDescription></Pick></Picks><Picks variant="register" legend="Format" defaultValue="quarto"><Pick value="octavo"><PickTitle>Octavo</PickTitle><PickDescription>The sheet folded three times: sixteen pages, small in the hand.</PickDescription></Pick><Pick value="quarto"><PickTitle>Quarto</PickTitle><PickDescription>Folded twice into eight pages. About half of Shakespeare’s plays first saw print this way.</PickDescription></Pick><Pick value="folio"><PickTitle>Folio</PickTitle><PickDescription>Folded once. Tall, grand and heavy on the lectern.</PickDescription></Pick></Picks></div>)}const line = "Plain, warm, unhurried."Contract
- Underneath: native radios, plus a hook that places pizzicato's dot and string and register's crosses.
- Anatomy:
<fieldset class="ot-picks" data-variant="pizzicato | rubric | watermark | register">, a legend, then<label><input type="radio">…any content…</label>per pick, usually<span class="ot-pick-title">and<span class="ot-pick-description">. A plain-text title is written as<span aria-hidden data-initial><span class="ot-pick-initial" data-text><span>I</span></span><span class="ot-pick-rest" data-text><span>nitial</span></span></span>plus the whole name in.ot-sr. A name in a script without capitals (its first letter is the same upper and lower case) is markeddata-caselessand not split: the initial holds a pilcrow and the rest holds the whole name. Pizzicato adds.ot-picks-stringand.ot-picks-dot; register adds.ot-picks-originand two.ot-picks-cross(data-corner="start | end"). - For choices that carry their own content, such as a specimen or a swatch. Yours: the chosen title crosses into the italic (a cross-fade of an italic copy in the same cell, so nothing moves), and its description steps up from pencil to graphite.
- Pizzicato (the default): one accent dot hangs in the margin beside the chosen title, level with its x-height. Pointing at another sketches a hairline ring where the dot would land; pressing tightens it. Choosing another slides the dot there (
--ot-picks-y, moderato, breath) along a hairline string that runs the length of the list; the string is pulled aside as the dot travels, let go on arrival, rings in five shrinking half-swings and fades back to silence (data-plucked, a registered--ot-picks-d). The title turns italic as the dot lands. Script measures the picks (--ot-picks-top,--ot-picks-len,--ot-picks-y) on choice, resize and font load, and setsdata-placed; until then the chosen pick's hover ring, filled in the accent, stands in for the dot, so nothing jumps at hydration. A first choice is plucked where it lands. - Rubric: the chosen title's initial is lifted out of the word and hung in the margin, two lines deep (title and the first description line), in the italic and the accent, the way a rubricator painted a section's one red letter. Every pick keeps the margin (
--ot-space-7, inside the label so focus and the pointer include the capital), so nothing reflows: the capital grows from its place in the word into the margin (andante, exhale) while a ghost of the small letter narrows to nothing and the rest of the name closes up to the edge and turns italic. Pointing leans the initial italic in place. A pick without a description keeps that second line free. It mirrors in right-to-left. A cased name on a right-to-left page (a Latin name among Arabic) begins at the end away from the margin, so its initial has nowhere to hang: the name stays whole, in its own order (an isolated left-to-right run), and the pilcrow hangs in the margin instead. A pick givendir="ltr"is a left-to-right block and hangs its capital in its own margin. A name without capitals, as in Arabic, Hebrew, Devanagari or Han, has no initial to hang, and lifting its first letter out would break a joined word; there the rubricator's other mark, an accent pilcrow (mirrored right to left), grows into the margin instead, and the name stays whole. - Watermark: the chosen title lies behind the list, huge (
--ot-fffin the expression italic) and faint (ink at 8%), set against the list's foot and end edge and cropped by them, the way a sheet shows its mould's mark held to the light and the poster's ghost numerals stand behind its words. Each title carries its own mark (.ot-pick-title::before, fromdata-text), so choosing another fades one mark down while the next comes up out of the paper (andante, exhale); nothing travels. The title itself crosses into the italic as pizzicato's does. Forced colours drop the mark. A title with rich content has no mark. - Register: the printer's registration crosses, as the posters mark their corners with a pair of + signs. Two accent crosses stand off the chosen pick's far corners, the top of its start side and the foot of its end side, by
--ot-picks-out. Script measures them (--ot-picks-x0,-y0,-x1,-y1) from.ot-picks-originon choice, resize and font load. Choosing another sends the pair there (moderato, breath), the far one two arpeggio steps behind, each turning a quarter the way the pick went (--ot-picks-turn); a cross turned a quarter is the same cross, so it only reads as turning while it moves. Pointing sketches the pair in pencil at that pick. Until it's measured, the chosen pick's own pair stands in, inked. Each pick keeps--ot-space-5either side for the crosses. - States: rest, hover (ink), focus (accent outline around the label), chosen, disabled (pencil at 55%, no hover). Forced colours: the dot, the rubric capital and the register crosses use
Highlight, the ring, string and pencil crossesCanvasText. Reduced motion: every tempo collapses, so the dot and capital arrive without travel. - Keyboard: native radio group (Tab into the chosen pick, arrow keys move the choice).
- The specimen uses it for the pair and scheme pickers.
Props
| Prop | Type | Default | What it does |
|---|---|---|---|
variant | "pizzicato" | "rubric" | "watermark" | "register" | "pizzicato" | How the choice is marked. pizzicato: one accent dot in the margin; choosing another slides it along a hairline string that is plucked, rings and falls silent. rubric: the chosen title's initial hangs in the margin two lines deep, in the italic and the accent, and the rest of the name closes up beside it; a name without capitals keeps whole and an accent pilcrow hangs there instead. watermark: the chosen title lies behind the list, huge, faint and cropped at its foot, and choosing another fades one mark into the next. register: two printer's registration crosses stand off the chosen pick's far corners and travel to the next, turning a quarter as they go; pointing sketches the pair in pencil. Nothing around it reflows. |
name | string | Shared by every radio so a form submits the choice. Generated if left out. | |
legend | ReactNode | The small label over the list. Without one, give the group an aria-label. | |
value / defaultValue | string | The chosen pick's value. | |
onValueChange | (value: string) => void | Called with the new value when the choice changes. | |
Pick value | string | What this choice stands for. | |
Pick children | ReactNode | Anything: a PickTitle and a PickDescription, a swatch, a specimen. Plain text is taken as the title. | |
PickTitle children | ReactNode | The pick's name. Plain text crosses into the italic when chosen, and it is the text rubric takes the initial from and watermark sets behind the list. A name in a script without capitals (Arabic, Hebrew, Devanagari, Han) isn't split; rubric hangs a pilcrow beside it. A name in the other direction from the page takes a dir attribute. | |
PickDescription | span props | A line under the title, in the pencil; graphite once chosen. Rubric's capital drops through its first line. | |
Pick labelClassName | string | Classes for the choice's label wrapper. className goes to the native radio. |
Craft
Where its move comes from
| Component | Reference | Move |
|---|---|---|
| Picks | The score's pizzicato; the rubricated initial | A plucked string carries the dot; or the chosen initial hangs in the margin (a pilcrow, for a script without capitals) |
| Picks, watermark | The poster's ghost numerals; the papermaker's watermark | The chosen name lies huge and faint behind the list |
| Picks, register | The posters' + corner signs; the printer's registration marks | Two crosses mark the chosen pick's far corners |
How it moves
| Component | Articulation | What moves |
|---|---|---|
| Picks | Pizzicato | A ring on hover; the dot slides to the choice along a string that is plucked and rings to silence |
| Picks, rubric | Rubrication | The initial leans on hover; chosen, it grows into the margin as a two-line accent capital and the name closes up in italic |
| Picks, watermark | Held to the light | One mark fades down and the next comes up out of the paper |
| Picks, register | Register | Pencil crosses on hover; chosen, the accent pair travels to the new corners, turning a quarter, the far one a beat behind |