Repository navigation
[Accessibility Gap] Make keyboard focus indicator robust to background contrast #324
Description
Buyer-visible outcome
Make keyboard focus clearly visible across Clearfolio's light panels, branded controls, and future workspace surfaces without relying on a focus-ring color that loses contrast after modern CSS color-mix() processing.
Fresh protected-main evidence — 2026-08-10
Protected main is 83ec6f7fe2b04bdcd28bf98ec350e41e55730a18.
src/main/resources/static/assets/viewer/viewer.css currently defines:
--focus: #ff595a;
:focus-visible {
outline: 3px solid var(--focus);
outline: 3px solid color-mix(in srgb, var(--focus), #ffffff 25%);
outline-offset: 3px;
}The second declaration wins in browsers that support color-mix(), so the effective ring is lighter than the fallback. The ring is commonly painted over white/light panel backgrounds. WCAG 2.2 Success Criterion 2.4.13 Focus Appearance (Level AAA) requires a qualifying focus-indicator area at least equivalent to a 2 CSS-pixel perimeter and a 3:1 change-of-contrast between focused and unfocused pixels.
A robust product-level solution should not depend on one mid-tone ring color working against every present/future background. A two-tone black/white ring can provide a high-contrast component across light and dark backgrounds while preserving a visible keyboard-focus boundary.
Required contract
- Preserve
:focus-visible; do not show the enhanced ring for ordinary pointer focus unless the user agent selectsfocus-visible. - Provide at least one focus-indicator band with >=3:1 change-of-contrast on light backgrounds and at least one with >=3:1 on dark backgrounds.
- Keep each qualifying band at least 2 CSS px thick; prefer 3 CSS px for the current UI.
- Do not remove browser focus indication, clip it intentionally, or encode focus solely through color change inside the component.
- Keep the treatment usable on links, buttons, file inputs, and other focusable controls.
- Preserve
prefers-reduced-motionbehavior; this change should add no animation.
Test-first acceptance
- Add a deterministic executable CSS contract test before production CSS changes.
- The RED test must prove the current modern-browser focus ring lacks the required robust light/dark-background contract.
- Implement the smallest CSS change, preferably a two-tone ring with independently visible >=2px bands.
- The test computes WCAG relative-luminance contrast for the declared ring colors and verifies the geometry/thickness contract rather than merely checking for an arbitrary string.
- Run the script suite and normal exact-head CI/security gates with zero required skips/failures.
- Keep this slice path-disjoint from active
viewer.jsgeneration-safety work (fix(viewer): suppress stale PDF render publication #323),demo.js/dom-utils.jsaccessibility work (fix(accessibility): make asynchronous viewer actions nested-safe #264), and Java/controller parent work (fix(security): harden audit pseudonymization and refresh Netty evidence #270/fix(viewer): remove hard-coded external company branding #318).
Standards basis
World Wide Web Consortium. (2023). Web Content Accessibility Guidelines (WCAG) 2.2, Success Criterion 2.4.13 Focus Appearance. https://www.w3.org/TR/WCAG22/#focus-appearance
World Wide Web Consortium. (2026). Understanding Success Criterion 2.4.13: Focus Appearance. https://www.w3.org/WAI/WCAG22/Understanding/focus-appearance.html
The W3C understanding document states that the qualifying focus-indicator area must have at least a 3:1 change-of-contrast and that only the sufficiently contrasting portion counts toward the minimum area.
Documentation boundary
PR #305 remains the canonical documentation writer. Do not create a competing PRD/TRD/Architecture authority for this slice. After implementation integrates, reconcile the accessibility/test/traceability authority through the canonical documentation line.
Activity