Skip to content
Style Guide
v0.1.0

Components

Forms

Labels above fields, one column, real HTML controls. Forms are where an interface most often becomes unusable, so the rules here are stricter than elsewhere.

Anatomy of a field

Every field is a .tmt-field containing a label, the control, and optionally help text and an error. The order in the markup is the order they are read.

Shown in the app and read aloud by voice assistants.

Text field
  • Labels sit above the field, always visible. Never a placeholder as a label — it disappears the moment someone types, and it fails contrast.
  • Every label has for matching the control's id. That makes the label clickable and gives the control its accessible name.
  • Help text is linked with aria-describedby, or it is invisible to a screen reader user.
  • Placeholders are examples, not instructions. If it matters, it goes in help text.

Controls

Inputs, select, textarea

Inputs use an 8px radius rather than the system's pill, so it is obvious where text will land. The select's chevron is drawn on the inline-end edge and moves to the other side automatically in Arabic.

Required and optional

Mark whichever is rarer. If most fields are required, mark the optional ones; if most are optional, mark the required ones. Marking everything teaches people to ignore the marks.

The asterisk is aria-hidden because the required attribute already conveys the state — otherwise a screen reader announces "star" and "required" both.

Checkboxes and radios

Native controls, tinted with accent-color. They inherit the platform's keyboard behaviour and its high-contrast rendering, which a custom-drawn control has to reimplement and usually gets wrong.

When should this run?

Choices

A group of radios or checkboxes belongs in a <fieldset> with a <legend>. Without it, a screen reader user hears the options but never the question.

Switches

A switch applies immediately. A checkbox waits for a submit. Using a switch inside a form with a Save button is the most common mistake with this control — people flip it, walk away, and lose the change.

Switches

The knob travels toward the inline end, so it moves right in English and left in Arabic. Because the state is carried by position rather than colour alone, the switch still reads correctly in greyscale — which it has to, in a monochrome system.

Form layout

  • One column. Two columns make people's eyes zig-zag and hide fields from anyone scanning down the left edge. The exception is genuinely paired data — city and postcode, expiry month and year.
  • 24px between fields (--tmt-space-5), 8px between a label and its control.
  • Group with a fieldset when several fields answer one question.
  • Match the field width to the content. A postcode field as wide as an address field tells the person the wrong thing about what to type.
  • Actions at the bottom, primary last, in a cluster.

Autofill and input types

Getting these right is the cheapest usability win in a form — and for people using voice control or a switch device, it can be the difference between a form taking twenty seconds and taking five minutes.

  • Set autocomplete on anything personal: name, email, tel, street-address, one-time-code.
  • Use the right typeemail, tel, url, number — so mobile keyboards match.
  • Use inputmode="numeric" for digit strings that are not really numbers, such as a verification code.
  • Never block paste. People paste passwords from managers and codes from messages.

Validation

The invalid state is carried by three signals at once — a 2px error border, an icon, and the message text — so it survives greyscale, colour blindness and a monochrome screen.

Enter an email address in the format name@example.com

Invalid field

When and how to validate, and how to build the error summary at the top of a long form, are covered in Form validation.