Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Accessibility

What is checked about the web UI against WCAG 2.2 level AA, how, and what is still open. Contrast is a test of its own (domain::skins_meet_contrast: every skin, text and controls); this page covers the structure of the pages and the keyboard.

Checked by a test on every page

templates::tests::every_rendered_page_is_accessible runs over every page that every_template_renders renders – every template in the states that test covers – and fails on (src/templates/accessibility.rs):

RuleWCAG
every input (except hidden, submit, button, reset), select and textarea has a label: <label for>, an enclosing <label>, aria-label or aria-labelledby1.3.1, 4.1.2
every button, link and input type=submit/button/reset/image has an accessible name: text, aria-label, aria-labelledby, title, or an image with alt inside2.4.4, 4.1.2
every img has an alt (empty for decoration)1.1.1
no tabindex above 02.4.3
<html lang> on a full page3.1.1
headings do not skip a level on the way down (h2 → h4)1.3.1
every <th> has a scope1.3.1
every <th> has a name: text (a visually hidden “Actions” for action columns), aria-label or title1.3.1
a full page with a <main> starts with a skip link: its first link points to the id of <main>2.4.1

A rule’s own test (the_checks_find_what_they_promise) feeds it a page with one violation of each kind and a page without any. When the test was added it found: <th> without scope in 21 templates (now scope="col", all of them in <thead>), two headings that skipped a level (the impact groups on the revision page and the assistant’s answer – each got a visually hidden <h2>), and two file inputs without a label (now aria-label). None of the fixes changes how a page looks.

The two later rules found 17 empty column headers (16 action columns, now a visually hidden “Actions”, and the corner of the inertia tensor on the mass page, now “Axis”) and the missing skip link: every page now starts with Skip to the main content, visible only while it has the focus.

Keyboard: the main flows

Checked by hand on 2026-11-06 in Chromium (the browser pane of the desktop app) against a throwaway database, with the keyboard only – Tab, Shift+Tab, Enter, the arrow keys and Escape. The focus was recorded at every step (focusin: element, :focus-visible, outline or shadow).

FlowResult
Sign inThe username has autofocus; Tab to the password, Enter signs in.
Dashboard and headerTab order: brand, navigation, search, notifications, account menu, then the page. Every stop has a visible focus (2 px outline, form fields 1 px outline plus a border in the focus colour). Landmarks: header, nav “Main”, the search form, main, footer.
Menus (Admin, account)Enter opens, Tab and ↑/↓ move inside, Escape closes and returns the focus to the menu button.
New itemEvery field labelled, order as on screen; Enter in a text field submits; a missing required field moves the focus to it (browser validation). Enter on a <select> does not submit – the browser’s behaviour, not the page’s.
Check-in“Check in…” (aria-expanded) opens the panel and moves the focus to its first field; Escape closes it and returns the focus to the button (fixed: Escape did nothing before, see below); Enter checks in.
BOMRevision rule, levels and group are labelled <select>s; ↑/↓ only change the choice, Enter or leaving the field applies it (WCAG 3.2.2, data-autosubmit); collapse/expand, export menu and the lines are reachable.
New change requestEvery field labelled, order as on screen, Enter raises the request.

Every message after a form (.flash) has role="status", an error role="alert", so screen readers announce it.

Fixed with this check: the panels opened by a data-toggle button (check-in, master data, lifecycle rules, file versions, the edit forms of changes, requests and project groups, acknowledging impacts) did not close with Escape. Now Escape inside an open panel closes it, sets aria-expanded="false" and returns the focus to the button that opened it (static/app.js); a menu inside a panel closes first.

Open

Each of these is an entry in docs/OPEN_WORK.md (Clients and packaging):

  • HTML built by JavaScript – the assistant sidebar, the BOM tree controls, the 3D viewer, the upload progress – is not covered by the template test, and the desktop app (desktop/ui) not at all.
  • No screen reader run. The checks above are structural; nobody has used the main flows with NVDA, JAWS or VoiceOver yet.
  • Focus of form fields is a 1 px outline plus a coloured border: enough for 2.4.7 (AA), below the 2 px of 2.4.13 (AAA).