Skip to content
Style Guide
v0.1.0

Patterns

Accessibility

WCAG 2.1 level AA is the floor for every Tomatico interface. Most of it is handled by using the system correctly — this page covers what the system cannot do for you.

The standard

Every Tomatico digital product meets WCAG 2.1 level AA. That is a floor, not a target, and it follows directly from the brand's human centered value: products "designed for people, made for life" cannot exclude people who use a keyboard, a screen reader, a magnifier or a switch device.

Using the documented components gets you most of the way. The failures that remain are almost always in the parts you write yourself: custom controls, focus management, and words.

What the system already handles

  • Contrast. Every semantic token pairing clears AA. See Colour → Contrast.
  • Focus. One visible 2px ring on every interactive element, offset by 2px so it reads on any surface, in both themes.
  • Touch targets. Controls are 44px tall by default.
  • Reduced motion. prefers-reduced-motion is honoured globally.
  • Text scaling. Sizes are in rem, so the browser's font setting is respected.
  • Direction. Logical properties throughout, so Arabic is not a second-class layout.
  • Status without colour. Alerts, badges and invalid fields each carry at least two non-colour signals.

Keyboard

Everything that can be done with a pointer can be done with a keyboard. Test it by unplugging the mouse.

  • Tab order follows the visual order. Do not reorder with tabindex above 0 — use the DOM order, and let CSS handle the arrangement.
  • No keyboard traps. Focus can always move on. The one legitimate trap is inside an open modal, and it has to release when the modal closes.
  • Focus is always visible. If you find outline: none anywhere, it is a bug.
  • A skip link comes first. .tmt-skip-link is hidden until focused.
  • Escape closes anything that opened over the page, and focus returns to whatever opened it.
KeyExpected
Tab / Shift+TabMove between controls, in reading order
EnterActivate a link or a button; submit a form
SpaceActivate a button; toggle a checkbox or switch
Arrow keysMove within a group: radios, tabs, a menu
EscapeClose a dialog, menu or drawer

Managing focus

This is what most often goes wrong in a single-page application, because nothing about it is visible to a sighted developer testing with a mouse.

  • Route change: move focus to the new page's <h1> (give it tabindex="-1"), and update the document title. Without this, a screen reader user hears nothing when the page changes.
  • Dialog opens: focus moves inside; the background is inert; closing returns focus to the trigger.
  • Content removed: if the focused element disappears, move focus somewhere deliberate first — otherwise it falls to the document body and the person starts again from the top.
  • Form fails validation: focus moves to the error summary. See Form validation.

Every control has a name

A control with no accessible name is announced as "button" and is unusable by voice control, which works by speaking the visible label.

<!-- Visible text is the name. Best case. -->
<button class="tmt-btn">Save changes</button>

<!-- Icon only: hidden text keeps the name in the DOM,
     so voice control users can still say it. -->
<button class="tmt-btn tmt-btn--icon">
  <span class="tmt-visually-hidden">Device settings</span>
  <svg aria-hidden="true">…</svg>
</button>

<!-- Fields: a real label, connected by for/id -->
<label class="tmt-label" for="room">Room</label>
<select class="tmt-select" id="room">…</select>
Accessible names

Prefer visible text, then visually hidden text, then aria-label. The first two also help people who use voice control or who simply cannot guess what an icon means.

Structure

  • One <h1> per page, then heading levels in order with none skipped. Screen reader users navigate by heading far more than by tabbing.
  • Landmarks: <header>, <nav>, <main>, <footer>. One <main>; label each <nav> if there is more than one.
  • Lists are lists, tables are tables, buttons are buttons. The native element carries behaviour and semantics that a <div> with ARIA has to reimplement — and usually reimplements incompletely.
  • Set lang on the page and on any passage in the other language, so the screen reader switches pronunciation.

Never colour alone

In a monochrome system this is easy to satisfy and easy to forget, because the greys look deliberate either way.

  • A status is a word plus an icon or a dot, never a hue on its own.
  • An invalid field has a heavier border and a message, not just a red edge.
  • A link inside body text is underlined, not merely a different weight.
  • Copy never says "the items in red" — it names the state.

The quickest check: view the screen in greyscale. Anything you can no longer distinguish is a failure.

Zoom and reflow

  • At 200% zoom, all content and function is still available.
  • At 400%, content reflows into a single column with no horizontal scrolling — except for things that genuinely need it, such as a wide data table.
  • Text spacing can be increased — line height to 1.5×, paragraph spacing to 2× — without anything being cut off. Fixed-height containers are what break this.
  • Nothing depends on hover alone. If information appears on hover, it also appears on focus, and it can be dismissed.

Testing

Automated tools catch perhaps a third of real problems. They are worth running, and they are not sufficient.

  • Keyboard pass. Unplug the mouse and complete the main task.
  • Screen reader pass. NVDA or Narrator on Windows, VoiceOver on macOS and iOS, TalkBack on Android. Fifteen minutes of listening finds more than an hour of auditing.
  • Zoom pass. 200% and 400%.
  • Greyscale pass. For colour independence.
  • RTL pass. See the RTL checklist.
  • Automated pass. axe DevTools, Lighthouse, or WAVE.

Pre-release checklist

  • Every image has alt — descriptive, or empty if decorative.
  • Every form control has a visible, connected label.
  • Every icon-only button has an accessible name.
  • Headings are in order, one <h1>.
  • Landmarks are present; multiple navs are labelled.
  • Focus is visible everywhere, and the tab order matches the visual order.
  • Nothing conveys meaning by colour alone.
  • Errors are announced and linked to their fields.
  • Content reflows at 400% zoom.
  • lang is set on the page and on passages in the other language.
  • Video has captions; audio has a transcript.
  • Nothing auto-plays, flashes more than three times a second, or moves without a way to stop it.