Accessibility on phones and iPads: contrast, touch targets, settings layout, screen-reader labels - #192
Merged
Conversation
… and iPads Audited with Playwright + axe-core (WCAG 2.2 AA) on phone and iPad sizes, portrait and landscape, light and dark, with touch emulation. Fixes: - Contrast: text-blue-500 links/values (3.76:1) -> blue-700/blue-400, inline links underlined; dark-mode greys on tabs, toggles and labels; Export green. - Touch targets: pointer-coarse:min-h-11 (44px) on reader, library, settings and footer controls; coarse-pointer CSS gives form fields 16px text (no iOS focus zoom) and 44px height. - Settings on phones: native section picker instead of a 191px sidebar that left the form 165px wide; dialog semantics, aria-current/aria-expanded, Escape to close, dvh height for iOS toolbars. - Screen readers: labelled version select and delete buttons, aria-pressed on mode toggles, oscilloscope minimap is a labelled button (was a clickable div over a canvas), mobile version picker is a dialog with full-row labels. - Phones: the settings gear shares the chapter row instead of its own row. tests/e2e/mobile-a11y.spec.ts gates all of it (zero axe violations, no overflow, no zooming fields, 44px targets with WCAG exceptions). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Review of #192: Settings and the mobile version picker were marked aria-modal but only handled Escape, so keyboard users could tab into the page behind them and lost their place on close. useModalDialog moves focus into the dialog on open, keeps Tab/Shift+Tab inside it, closes on Escape and returns focus to the opener. IllustrationRouteDialog had the same Escape-only pattern and now uses the hook too. Unit tests cover focus entry, both wrap directions, recapturing escaped focus and focus return (mutation-checked). Playwright keyboard tests for both dialogs fail on the previous commit and pass now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
Resolve the docs/WORKLOG.md conflict by keeping both entries in time order, and correct the accessibility entry's case count (6 skipped, plus 3 keyboard cases). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
This branch was successfully deployed
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.
Owner request: make the mobile and iPad UI work well, with accessibility.
Audit (before)
Playwright with axe-core (WCAG 2.2 AA) covered the library, reader, text-selection sheet and settings at phone 390×844 / 844×390 and iPad 820×1180 / 1180×820, in light and dark mode, with touch emulation.
text-blue-500on white at 3.76:1; the minimum is 4.5:1.divover a canvas (the oscilloscope minimap), mode toggles that didn't announce their state, and modal overlays with no dialog semantics or focus management.Changes
blue-700/dark:blue-400, and inline links are underlined. Dark-mode greys on tabs, toggles and labels are fixed, and Export usesgreen-700.pointer-coarse:min-h-11Tailwind variant gives controls 44 px on touch screens only, so desktop density is unchanged.index.cssgives form fields 16 px text (no iOS zoom) and a 44 px height.sm, a labelled native section picker replaces the sidebar (iOS shows its picker wheel). On larger screens the sidebar is anavlandmark witharia-currentandaria-expanded. The modal usesdvhheight so iOS toolbars don't clip it.useModalDialog, WAI-ARIA dialog pattern): Settings, the mobile version picker and the illustration dialog each:aria-pressed.Gate
tests/e2e/mobile-a11y.spec.ts:md, leaving 34 applicable. Each requires:ac2acc1and pass now.Putting back one old link color fails the matrix. It's a local gate, because Playwright isn't in CI yet (T0.4). Run it with
npx playwright test tests/e2e/mobile-a11y.spec.ts(37 pass, 6 skipped).Review fix
An independent review of
ac2acc1found that the dialogs were markedaria-modalbut only handled Escape. Commit7bb5217addsuseModalDialogand its tests. The unit tests cover focus entry, wrapping in both directions, recapturing escaped focus and focus return; the focus-return test was mutation-checked. The review also corrected the applicable-case count to 34.Verification
tscand the Playwright tsconfig: clean.eslint: 0 errors.vite build: pass.vitest run: 9,609 passed, 1 failed. The failure is the known Node-22-onlyindrasNetImageProvider.test.tscase.mobile-selection-affordanceandchapter-change-perfspecs pass.Limits
🤖 Generated with Claude Code
https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W