Skip to the content

What the build checks

  • Text contrast (1.4.3). Every text colour reaches 4.5:1 on color.surface.default, raised and inset, in both themes. The test lists the deliberate misses by name: color.text.tertiary and color.transit.delay.unknown, which are only for hints, captions and the "—" of an unknown delay or figure, always next to stronger text. Status and brand text also reach 4.5:1 on their own tinted surfaces. Under a quiet control's hover and pressed layers, text keeps 4.5:1 on default and raised; on inset, the light theme's brand outline label drops to 4.3:1 on hover and 4.0:1 while pressed, so a brand outline button sits on default or raised.
  • Non-text contrast (1.4.11). What shows where a control is, or what state something is in, reaches 3:1 against every surface: color.border.control, color.border.brand, the focus ring and the status fills. Decorative lines, color.border.subtle and color.border.strong, are exempt, and their descriptions say so. On the map, color.map.aircraft reaches 3:1 on every ground a plane flies or taxis over (Map).
  • The focus ring (2.4.7, 1.4.11) reaches 3:1 on every surface and on the map's land, water and parks.
  • The surface ladder. color.surface.inset stands apart from color.surface.raised by at least 1.15:1 in both themes, so an inset track reads without a border. See Elevation.
  • Line badges. Label colours on line colours are measured, and the official pairs that miss are listed. See Semantic colours.
  • Reduced motion (2.3.3, a AAA criterion met anyway) lives in the tokens: when the system asks for less motion, transitions take 0.01 ms. See Motion.

Text on surfaces

The ratio each pair reaches, against the minimum of 4.5:1.
LightDark
Colouron surface.defaulton surface.raisedon surface.inseton surface.defaulton surface.raisedon surface.inset
color.text.primary
17.26:1
17.92:1
15.32:1
15.32:1
13.45:1
11.21:1
color.text.secondary
7.63:1
7.92:1
6.77:1
7.80:1
6.85:1
5.71:1
color.text.tertiary
3.85:1, under
4.00:1, under
3.42:1, under
4.48:1, under
3.93:1, under
3.28:1, under
color.text.success
5.34:1
5.54:1
4.74:1
8.57:1
7.52:1
6.27:1
color.text.warning
5.38:1
5.59:1
4.78:1
8.60:1
7.55:1
6.29:1
color.text.danger
6.12:1
6.35:1
5.44:1
7.50:1
6.59:1
5.49:1
color.text.info
7.06:1
7.32:1
6.26:1
7.51:1
6.59:1
5.49:1
color.text.brand
5.41:1
5.62:1
4.81:1
9.82:1
8.62:1
7.19:1
color.transit.delay.on-time
5.34:1
5.54:1
4.74:1
8.57:1
7.52:1
6.27:1
color.transit.delay.slight
17.26:1
17.92:1
15.32:1
15.32:1
13.45:1
11.21:1
color.transit.delay.late
6.12:1
6.35:1
5.44:1
7.50:1
6.59:1
5.49:1
color.transit.delay.early
7.06:1
7.32:1
6.26:1
7.51:1
6.59:1
5.49:1
color.transit.delay.unknown
3.85:1, under
4.00:1, under
3.42:1, under
4.48:1, under
3.93:1, under
3.28:1, under
color.transit.severity.delay
6.12:1
6.35:1
5.44:1
7.50:1
6.59:1
5.49:1
color.transit.severity.data
7.63:1
7.92:1
6.77:1
7.80:1
6.85:1
5.71:1
color.transit.severity.diversion
7.06:1
7.32:1
6.26:1
7.51:1
6.59:1
5.49:1
color.transit.severity.planned
7.63:1
7.92:1
6.77:1
7.80:1
6.85:1
5.71:1
color.transit.severity.notice
7.63:1
7.92:1
6.77:1
7.80:1
6.85:1
5.71:1

Controls, focus and status fills on surfaces

The ratio each pair reaches, against the minimum of 3:1.
LightDark
Colouron surface.defaulton surface.raisedon surface.inseton surface.defaulton surface.raisedon surface.inset
color.border.control
3.10:1
3.12:1
3.03:1
3.32:1
3.26:1
3.04:1
color.border.brand
5.41:1
5.62:1
4.81:1
9.82:1
8.62:1
7.19:1
color.border.focus
17.26:1
17.92:1
15.32:1
15.32:1
13.45:1
11.21:1
color.status.success
3.87:1
4.02:1
3.44:1
8.57:1
7.52:1
6.27:1
color.status.warning
4.12:1
4.28:1
3.66:1
8.60:1
7.55:1
6.29:1
color.status.danger
4.99:1
5.18:1
4.43:1
7.50:1
6.59:1
5.49:1
color.status.info
5.71:1
5.92:1
5.07:1
7.51:1
6.59:1
5.49:1

The focus ring on the map

The ratio each pair reaches, against the minimum of 3:1.
LightDark
Colouron map.landon map.wateron map.parkon map.landon map.wateron map.park
color.border.focus
15.48:1
11.78:1
13.61:1
14.88:1
16.27:1
13.89:1

Rules

  • Focus. Every interactive element shows the ring on :focus-visible: a focus.width solid outline in color.border.focus, focus.offset away from the element. perron.css sets it for the whole page. Never remove an outline without drawing the ring another way.
  • Targets (2.5.8). Anything people press is at least size.target-min square, or has that much room around it. Perron's smallest control, a switch's track, is size.target-min tall and wider than that; the rest are larger, a small button size.button-sm.
  • Colour never alone (1.4.1). A status colour comes with a word or an icon, a data state with its name next to the dot, a line colour with the line's name.
  • Hover (1.4.13). Anything shown on hover is also reachable by selecting the item, because touch and keyboard users never see hover. A hover card stays while the pointer is over it and closes with Esc.
  • Keys. Esc closes the topmost thing first: a dialog, then a detail panel, then a highlight. + and − zoom, arrow keys pan.
  • State in words. A toggle says its state in words as well as in looks, and says it once, one of two ways. A plain button whose label is an action and its only word changes its words with the state ("Follow" / "Following") and has no pressed state. A control with a pressed or checked state keeps its label, and its role tells the ear the state: a toggle button's or a filter chip's aria-pressed says pressed, a switch's role="switch" says on or off. Never both: a label that changes on a control with aria-pressed is heard as "Following, toggle button, pressed". The eye gets more than a hue: a switch's thumb moves as its track fills, and a chip's fill turns to ink. One primary action per panel.
  • Moving things. Loops (the follow blink, the report and selection pulses, and the progress bar's sweep) stop in their component when the system asks for less motion. The tokens only shorten transitions.
TokenValue
focus.widthWidth of the focus ring
2 pxborder.width.050
focus.offsetGap between the focused element and its ring
2 px
size.target-minSmallest touch or pointer target, from WCAG 2.2 target size (minimum)
24 px

What a person checks

Before a screen ships, check what the build can't:

  • Keyboard. Every action is reachable in a sensible order. Only an open dialog traps focus, and closing anything returns focus to where it came from.
  • Names. Every control has an accessible name; an icon button carries a label. The map has a text alternative: the vehicle list.
  • Images. Images and the mark have alt text, or are hidden from assistive technology when they are decoration.
  • Zoom and reflow (1.4.4, 1.4.10). At 200% zoom and at 320 px wide, nothing is cut off or overlaps, and only the map scrolls sideways.
  • Text spacing (1.4.12). Wider line, letter and word spacing breaks nothing.
  • Announcements. Live updates, such as countdowns and moving vehicles, don't flood a screen reader: a polite live region announces changes of state only.
  • Forced colours. In Windows' contrast themes, the focus ring and the selected state still show. The vehicle dot shapes keep each data state readable without colour: each of the five has a shape of its own, and no signal, a solid dot like live, is cut by a slash (Data states).