The theme contract
A theme may change how an App looks, never whether it can be used. Every look
an App can wear, a built-in or one of its own, keeps thirteen promises.
tablewalk check holds the ones the theme’s spec decides; tablewalk grade
measures the ones only a drawn page shows. Every finding of those codes
carries its promise, "promise": "C2", in check --json and in grade’s JSON,
and tablewalk explain C2 prints the row below.
npx tablewalk grade . --config tablewalk.json --theme allnpx tablewalk grade . --config tablewalk.json --theme all --palette all --as all --json--theme all grades every theme the App can wear: its own look, the built-in
looks and each of ui.customThemes. Each row is a theme, and each column a
window: 1280, 390, 320 and 390 in the dark. --palette all adds each other
palette of a theme at 390 and 390 in the dark, reading only C1, C2, C3 and C6,
because a palette changes colors and moves nothing. --as all adds a row for a
signed-out visitor and one for each role a person signs in as. A cell is ✓ or
its count of findings. Under the table, each failing cell’s first finding gives
its promise, code, row, window and page, and, where a theme’s color caused it,
the token and a value that passes. Any error fails the run with exit code 2.
| Promise | Measured by | What it promises | Fix |
|---|---|---|---|
C1 |
check theme-contrast, grade low-contrast |
Text readable: words at 4.5:1 on every ground they are drawn on, 3:1 when large | The color the finding names, or tablewalk check --fix |
C2 |
check theme-edge, theme-shadow, grade faint-edge |
Controls visible: a field’s, a select’s and a picker’s edge at 3:1 on the field and on what it sits on, and a lift that is a shadow, not a glow (a theme draws no glow anywhere: its stylesheet’s box-shadow is one of the look’s lifts and takes no text-shadow or filter) |
A darker lineControl (check --fix writes one that passes); a shadow darker than the ground |
C3 |
check theme-focus, grade hidden-focus |
Focus visible: the ring at least 2px and 3:1 on every ground a focusable sits on, the menu’s included (grade tabs through it) | A focus color that reads on the page, a panel and a raised row |
C4 |
grade small-target |
Targets big enough: 40px each way on a phone, 24px at a desk | Padding, not a smaller box; report the platform’s own controls |
C5 |
grade overlap, clipped-text, clipped-number, sideways-scroll, header-wrap |
Nothing cut or overlapping, down to a phone 320 wide | A smaller corner or density in the theme; the App’s own layout fixes are in design checks |
C6 |
grade color-only |
Not by color alone: a toned mark always has its word or a name beside it | Say the value: a status as its dot and word, a mark with an aria-label |
C7 |
check theme-chart |
Charts distinguishable: neighboring series 8 apart for color-blind readers, 10 to normal vision | The order tablewalk check suggests |
C8 |
check theme-type, grade long-measure |
Type legible: no text below the look’s size, no weight a face does not ship, prose no wider than 80 characters a line | Give prose a narrower column; ship the face at the weight a role asks for; a theme cannot shrink text |
C9 |
grade unsafe-motion |
Motion safe: nothing moves under reduced motion, nothing takes past 200ms, nothing loops | The platform’s motion only; report a part that moves |
C10 |
check theme-dark, grade’s 390-dark window |
Dark complete: every color and picture has a dark answer | The dark color the window’s finding names; a logo picture’s dark |
C11 |
check theme-budget, grade layout-shift, heavy-theme |
Stays fast: faces 150 KB together, the theme’s files light on a cold visit, no shift once drawn | Fewer weights, a variable face, a smaller logo |
C12 |
check theme-print, grade print-contrast |
Print reads: the accent, links and words at 4.5:1 on white paper | A light accent and link that read on white |
C13 |
check theme-part, theme-band, theme-css, theme-contract, grade changed-app |
Same App: a theme changes how the App looks, never which controls a reader can reach or where a box stands (a control folded into a “More” menu by larger type is still reachable: grade opens the fold and finds it there; a shortcut hint and a chart’s tick labels are decoration); a part it dresses keeps its words legible | Dress a part in roles whose ink reads on its ground; say a part’s size or visibility in the App, not its theme |
The C-rules bound an App’s theme; design.md’s refusal list binds the built-in looks and what the platform draws (themes).