Appearance
Choose the look: scheme, key and type pair as three lists of picks, and the answer written back as one sentence, “Cotton, in ultramarine, set in Archivo and Bodoni.”, which the night toggle finishes. The new page opens as a circle from whatever you touched.
Report an issue with AppearanceExample
The house
Its own key
Keyed, by night
Install
Run it in a project that has the shadcn CLI set up. It brings the 0nlyType base, mode-toggle, and picks along.
npx shadcn@latest add https:// thedirectors.agency/ ui/ r/appearance.jsonUsage
import { Appearance } from "@/components/ui/appearance"// Live: choosing here retunes this page, as the Tune panel in the bar does.export default function Example() {return <Appearance className="w-full max-w-[52rem]" />}Contract
- Underneath: native, through
picksandmode-toggle, plus a hook that reads and writes the four switches on<html>. - Anatomy:
<div class="ot-appearance">holding<p class="ot-appearance-answer"><output>…</output> <button class="ot-mode" data-variant="sentence">…</button></p>and<div class="ot-appearance-picks">with threeot-picks(pizzicato): Scheme (cotton, blueprint, statue, silence, riso), Key ("its own", its description naming the scheme's own accent, then ultramarine, viridian, ember, violet) and Pair (parma, press, paris, salon, each with its faces as the description). - The move, after "Healthy habits → for creatives", where the voice runs into the italic on one line of thought: the choice is written back as one sentence over the lists, "Cotton, in ultramarine, set in Archivo and Bodoni.", and the night toggle finishes it, "Read by light." Ours in roman and graphite; yours, the three words you chose, in the italic and ink. The sentence is an
<output>for the three lists, so a reader hears the new sentence after each choice. No key reads the scheme's own accent by name (cotton ultramarine, blueprint orange, statue gold, silence cobalt, riso magenta). - Layout: the lists stand two across with the pair under them, or three across once the control is 36rem wide (a container query); the answer steps up from
--ot-mpto--ot-mfthere. The picks are set at--ot-p, closer than a standalone list. One accent in view: only the list you're in, or were last in (data-here, the scheme to begin with), marks its choice with the accent dot; the others set theirs in ink, and their italic titles still say what's chosen. - It writes only the four switches (
data-mode,data-scheme,data-key,data-pair; cotton and parma are no attribute) and keeps them together as one JSON object under0nlytype-themein localStorage.useAppearance()reads<html>through a MutationObserver, so a head script, the page and every control agree. Withvalueit holds nothing and writes nothing:onValueChange(value, from)reports. - Motion: the new appearance opens over the old as a circle from the control you touched (a view transition, andante, exhale, so the circle is already wide as the press lands;
--ot-appearance-x,--ot-appearance-yon<html>). Under the circle the colours are already new, so the body's own colour fade is off for as long as the transition runs (:active-view-transition). Reduced motion, or no view transitions, changes it at once, and there the body's colour fade stays. - Faces: a pair's fonts load only when the page first asks for them. Pointing at or focusing the pair list fetches every pair's faces (
warmPairs()), and choosing a pair whose faces have not arrived waits up to 400ms for them before the page turns, so the new page opens already set in its letters. The control shows the choice at once while it waits; a second change made meanwhile builds on it. The page restores the stored choice before first paint with a one-line script in<head>(the docs site'stheme-script.tsx). - States: those of picks and the mode toggle. Keyboard: Tab through the toggle and the three groups; arrow keys move each choice.
- The site's bar opens it from Tune, in a popover, beside the dimmer toggle.
Props
| Prop | Type | Default | What it does |
|---|---|---|---|
value | { mode?, scheme?, key?, pair? } | The appearance, when you hold it (controlled). Leave it out and the control reads the four switches on <html>, writes them there and keeps them in localStorage under 0nlytype-theme. | |
onValueChange | (value, from) => void | Called with the whole appearance after each change, and the element that made it. | |
useAppearance() | [value, set(patch, from?)] | The appearance on <html>, for your own controls: set a patch and it is applied, kept, and opens from the element you pass (or the focused one). | |
applyAppearance(value, from?) | function | The same, outside React. Restore the stored choice before first paint with a one-line script in <head> that reads 0nlytype-theme and sets the attributes. | |
SCHEMES, KEYS, PAIRS | arrays | The names the switches take: five schemes, four keys and four pairs, each pair with its faces in words. |
Craft
Where its move comes from
| Component | Reference | Move |
|---|---|---|
| Appearance | "Healthy habits → for creatives"; the score's pizzicato (picks) | The choice written back as one sentence, yours in the italic; the night toggle finishes it |
How it moves
| Component | Articulation | What moves |
|---|---|---|
| Appearance | Opening | The new page opens over the old as a circle from the control you touched |