Accessibility: a title on every control, AA contrast, kept focus and reduced motion - #34
Merged
Merged
Conversation
The repo rule gives every interactive control a title, and nothing checked it: 248 controls had none. The test parses every component with the TypeScript compiler and lists each button, link, form field, summary and role-carrying control without a title attribute or a spread that could carry one. The map, visits and search components are held out while their rewrite lands.
A mouse user hovering a button, link or field got no tooltip naming it on 199 controls, against the repo rule. Each now carries a title in the words of its visible label, its aria-label or its field label, from the existing strings in every language. MoreButton takes its label as a string so it can reuse it as the title.
…idth The gate covered five screens in the light scheme at desktop width, so contrast failures on the place card, the Countries list, the photo viewer, About, the Places chips in dark and the phone Stats numbers went unseen. Each screen and dialog is now its own test, from a restored backup with trips, stories and photos, in light, dark and at 375 px. The search results stay out while their nested button is reworked.
Six pairs failed axe: the visited green on the beige card and in the Countries badges, the place card's green in dark, the photo caption on the dark viewer, the faded About version line, and the Filter chip in dark, which drew grey system button colour behind muted text. The visited green darkens one step, the place card reads the theme's visited token, the caption takes the viewer's own light grey, the version line drops its fade and the chip draws no background.
New story hides itself while the composer is open, so clicking it dropped keyboard focus on the page body, and closing the composer did the same. Opening now focuses the composer's Place field, and Cancel, Escape or Save give focus back to the control that opened it, or to New story.
Ten controls vanished when pressed and dropped keyboard focus on the page body: New trip, the boarding-pass open and Close buttons, the world poster Close, Disconnect, the sync guard and the offline-map reset confirm, the late-night day choice, the phone recommendation in the intro, and Publish when closed. A small hook now hands focus to the control that takes the removed one's place, only when focus was lost, and Publish returns focus to its opener as About already does.
…ntent With reduced motion asked for, opening the journal composer or editing a trip still scrolled the page smoothly, and the global rule that stops transitions matched elements but not their ::before and ::after, so the Settings disclosure arrow still turned. Both scrolls now jump under reduced motion, and the rule covers generated content. Editing a trip while its form was closed scrolled nowhere, since the form was not yet drawn; the scroll now waits for it. Map camera moves already jump: MapLibre skips non-essential animation under reduced motion and the app passes a zero duration.
- JournalScreen: main moved writing onto the StoryComposer page and dropped the inline form and the late-night day choice, so main's side is kept there. The titles this branch put on the reader's controls stay, now labelled with entryLabel, since a postcard's place is optional. - New story focus: the fix moves to the page model. Write a postcard hands focus back to itself when the composer it opened closes, and an edit opens on the composer's date field, since the Edit button that opened it is gone. journalComposerFocus.spec.tsx drives the page switch App makes. - TripComposer: main's chain-based removeStopAt with this branch's title on the remove button; main's per-stop dates replace the year and month fields this branch had titled. - a11y.spec.ts: the per-screen matrix in light, dark and at 375px stays; main's postcard composer test becomes its postcard composer screen with details open, and the matrix gains the station browse and asserts the trip composer's per-stop dates. - Reduced motion and focus handoff: the journal cases go with the inline composer and the day choice they covered.
The title guard listed 26 controls main brought in without one: every field and button of the postcard composer, the Journal's tag chips, the per-stop date, legacy date chip and linked postcards of the trip composer, the route map's kind filter and the station dataset picker in Settings. Each takes the label or aria-label it already shows, from existing en, fr and ko keys.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Based on #31, whose branch it builds on; merge that first.
248 controls had no
title, although the repo's rule asks one of every interactive control. A unit test now parses every.tsxfile and fails on a control with neither atitlenor a spread that could carry one. 199 controls got a title taken from their visible label oraria-label; the other 49 sit in the map, places and search files another branch is rewriting, and wait in a marked block of the test until it lands.Six colour pairs were below the 4.5:1 AA contrast, the worst a photo caption at 2.48 and a dark-mode chip at 2.19. They now reach at least 4.6, and the look stays the same except that the Filter chip loses a grey fill it never meant to have.
The axe check now runs on 29 screens and dialogs, each in light, dark and at phone width, one test per screen so a failure names it. The only violation left is the nested buttons in search results, which the same pending branch owns.
New story and ten other buttons that remove themselves when pressed dropped keyboard focus onto the page. Focus now moves into what opened and back to the opener when it closes. Page scrolls and generated content also honour reduced motion, and editing a trip whose form was closed scrolls to the form again.