The four moves
Fire, rule, cell and fill: every component speaks with these.
Cell
Point, press, tab
Fire
Point at the bar
Held
-
Fire
pointerenter
A flare at the point the interaction starts. It plays once; hold the clock to see it.
- Row
Rule
pointerenter, :focus-visible
Developed in --state the full length of a line already on the page.
-
Cell
hover
Hot: a --state fill that keeps moving.
-
Cell, selected
aria-current
A still --ink fill.
-
Fill, burnt
hover
--state burnt across the solid block from its cell.
- On
Fill, selected
aria-pressed
--ink is selected.
Anatomy
| Fire | a square-banded flare of grain where an interaction starts: 280ms (--duration-fire, 280ms) |
|---|---|
| Rule | develops in --state from the pointer, both ways, in 140ms (--duration-develop, 140ms); retracts in 100ms |
| Cell | a --tissue ring at rest, --state and firing when hot, its edge wobbling while hot, --ink when selected |
| Fill | a solid button burns --state from its cell in 160ms (--duration-burn); a choice between peers pulses along their rule in 200ms (--duration-pulse) |
| Dot | 2px, through the 8×8 Bayer screen |
| Where a move starts | at the pointer on broad surfaces, at the control’s own cell on compact ones |
| Reduced motion | every state lands at once and nothing fires |
Timings are read from rule.ts, ui.ts and global.css at build time.
Decisions
-
One interaction, one flare
Where a rule starts at a cell, the cell fires and the rule only develops out of it (Oct 2026). Until then a control with a label fired twice.
-
Faster rules
The rule went from ~260ms to 140ms in Oct 2026: Shan asked for it faster, snappier and more luminant, like the cursor firing.
-
Nothing slides or fades
Panels and slides change by a hard cut. Each element gets its own canvas behind its content, drawing only while something moves.
-
Mirrored timings
The --duration-* tokens and the constants in rule.ts and ui.ts move together; the figures above are read from both at build time.