Accessibility
One focused chapter from the Thorbis interface research. 9 rules. Read the research index for every chapter and focused study.
Accessibility
- Measure contrast with APCA. Prefer APCA (opens in a new tab) (Andrew Somers, over WCAG 2 for perceptual contrast. Body text targets |Lc| ≥ 75 (prefer 90). Labels and headlines ≥ 60. UI components ≥ 30. Disabled and placeholder text may sit at 30, never below 15.
- Fix contrast with lightness, not hue. In OKLCH, move L first and keep C and H. On a dark canvas (lightness below 0.25) body text wants lightness above 0.9. On a light canvas (lightness above 0.9) it wants lightness below 0.35. Mid-lightness surfaces cannot reach body contrast, change the surface.
- Never use a positive tabindex.
tabindex="0"adds a custom control to the natural order.tabindex="-1"is for programmatic focus. A positive value hijacks the whole page, fix the DOM order instead. - One Tab stop per composite widget. Tabs, menus, toolbars, and radio groups use a roving tabindex: the active item is
0, siblings are-1, arrows move both focus and the zero. Follow the APG pattern (opens in a new tab) for that widget. - Hide visually, not from assistive tech. Use the 1px clip pattern (
sr-only) for names that sighted users get from layout. Neverdisplay: noneor a 0×0 box, some readers skip those. - Announce with the smallest tool. If focus already moves there, stop. If it is tied to a field, use
aria-describedby. If it is a toast, count, or “Saved”, use a politerole="status"that already exists in the DOM. Reserverole="alert"for urgent, unbound errors. - Honor forced colors. In
forced-colors: active, keep system colors. Never freeze an authored ring withforced-color-adjust: noneunless the control stays perceivable. - Toasts never steal focus. Announce them and leave the caret where the operator is working. Give a generous timeout or a dismiss. Never put the only path to an action inside an auto-dismissing toast.
I built this for the dispatcher at 7 a.m., the tech in a crawlspace, and the owner closing the books. Quiet chrome. Precise work. I’m still learning. These are the notes.
Applied bookmark research
Reviewed 2026-09-06. These examples reinforce the existing owners; they do not introduce another visual style or claim the product behavior is implemented. Read the 26-source review and access limits.
A control keeps its meaning through every state
A button that changes width, a field that loses input, or a dialog that loses focus breaks the task even when the resting design looks precise.
Review the approved primitive as a sequence: resting, focused, activated, pending, resolved, and recovered. Keep the action label and footprint stable, associate errors with their fields, and preserve a visible keyboard path.
Thorbis example. Save estimate remains Save estimate while its state mark changes. A validation error keeps the entered values, explains the repair beside the field, and moves focus only when the interaction calls for it.
Verify. Test Tab, Shift-Tab, Enter, Escape where applicable, paste, invalid input, rapid activation, and a slow response. Repeat at 390px, in both themes, with zoom and reduced motion.
Do not import. No hand-built duplicate primitive, hidden label, disabled browser zoom, or borrowed shadow-only outer edge that violates D-017.
Open the ui skill · Evidence: Web Interface Guidelines; Invisible Details; components.build; Details that make interfaces feel better
Transfer the intent, not the desktop gesture
An interaction that works with a precise pointer or modifier key may be unusable for a tech holding a phone.
Preserve the record and task while adapting the visible action path to the device. Use the existing native owner for target sizing, safe areas, focus, and host behavior; no critical action relies only on hover or a hidden gesture.
Thorbis example. A field photo remains attached to the same job when the tech changes orientation or returns from another app. The visible capture action and retry path remain available without discovering a desktop shortcut.
Verify. Check one-handed use, software keyboard opening, text enlargement, orientation, focus visibility, and reduced motion on the relevant device. Keep permission refusal and return-from-interruption states in the review.
Do not import. No desktop hover contract on a phone, blocked zoom, silent clipboard access, or unverified claim that a web imitation is native behavior.
Open the native skill · Evidence: Web Interface Guidelines; Design Engineer Principles; Devouring Details