feat(ui): high-contrast theme variants, WCAG AA/AAA (LC-192) #238

Merged
nrupard merged 1 commit from feat/lc-192-high-contrast into main 2026-05-27 21:09:08 +02:00
Owner

High-contrast theme variants on the LC-190 token foundation + LC-191 switching.

What lands

  • Palettes (main.css): [data-theme="hc-light"] and [data-theme="hc-dark"] - black/white surfaces + text (AAA for body text), always-visible pure-black/white borders (no faint greys), and 700-ish state colors (success/warning/danger) that pass AA against their surface. color-scheme set per variant so native controls/scrollbars match.
  • Focus ring: :focus-visible now uses var(--ring) (themes with the palette) and is thickened to 3px with a larger offset under the HC themes.
  • Bootstrap (base.html): explicit values (light/dark/hc-light/hc-dark) pass through; system upgrades to the matching high-contrast variant when prefers-contrast: more (and follows prefers-color-scheme); <meta theme-color> mapped per theme; re-resolves on OS color-scheme and contrast changes while on system.
  • Allowlists extended to accept the two HC values in all three spots: User::theme_or_system, post_appearance, and the lc-theme cookie-sync in resolve_locale.
  • Picker: Settings -> Appearance gains "High contrast (light/dark)"; theme-hc-light / theme-hc-dark labels in en + es.

Notes

  • No new migration - reuses the users.theme column.
  • Like dark, the HC palettes recolor the whole app once LC-193 migrates templates onto the tokens; the switch + auto-detection are complete here.

Verification

just test + just test-saas green; cargo fmt --all clean; i18n_catalog gate passes. Contrast: hc body text is #000-on-#fff / #fff-on-#000 (AAA); state colors are 700/400 shades chosen for >= AA on their surface.

High-contrast theme variants on the LC-190 token foundation + LC-191 switching. ## What lands - **Palettes** (`main.css`): `[data-theme="hc-light"]` and `[data-theme="hc-dark"]` - black/white surfaces + text (AAA for body text), **always-visible pure-black/white borders** (no faint greys), and 700-ish state colors (success/warning/danger) that pass AA against their surface. `color-scheme` set per variant so native controls/scrollbars match. - **Focus ring**: `:focus-visible` now uses `var(--ring)` (themes with the palette) and is **thickened to 3px with a larger offset under the HC themes**. - **Bootstrap** (`base.html`): explicit values (`light`/`dark`/`hc-light`/`hc-dark`) pass through; **`system` upgrades to the matching high-contrast variant when `prefers-contrast: more`** (and follows `prefers-color-scheme`); `<meta theme-color>` mapped per theme; re-resolves on OS color-scheme **and contrast** changes while on system. - **Allowlists** extended to accept the two HC values in all three spots: `User::theme_or_system`, `post_appearance`, and the `lc-theme` cookie-sync in `resolve_locale`. - **Picker**: Settings -> Appearance gains "High contrast (light/dark)"; `theme-hc-light` / `theme-hc-dark` labels in en + es. ## Notes - No new migration - reuses the `users.theme` column. - Like dark, the HC palettes recolor the whole app once **LC-193** migrates templates onto the tokens; the switch + auto-detection are complete here. ## Verification `just test` + `just test-saas` green; `cargo fmt --all` clean; `i18n_catalog` gate passes. Contrast: hc body text is #000-on-#fff / #fff-on-#000 (AAA); state colors are 700/400 shades chosen for >= AA on their surface.
feat(ui): high-contrast theme variants, WCAG AA/AAA (LC-192)
All checks were successful
check-secrets / Nosey parker (push) Successful in 3s
check-secrets / TruffleHog (push) Successful in 3s
check-secrets / Kingfisher (push) Successful in 5s
check-secrets / Kingfisher (pull_request) Successful in 4s
check-secrets / TruffleHog (pull_request) Successful in 5s
check-secrets / Nosey parker (pull_request) Successful in 5s
Check / clippy + fmt + tests (pull_request) Successful in 2m13s
Create release / Create release from merged PR (pull_request) Has been skipped
fad8d14895
Adds hc-light + hc-dark on the LC-190/LC-191 theming machinery.

- main.css: [data-theme="hc-light"] / [data-theme="hc-dark"] token palettes - black/white surfaces + text (AAA body), always-visible pure-black/white borders, 700-shade state colors that pass AA on their surface, color-scheme set per variant. :focus-visible now uses var(--ring) and is thickened (3px, larger offset) under the HC themes.
- base.html bootstrap: explicit values (light/dark/hc-light/hc-dark) pass through; "system"/unset resolves prefers-color-scheme and upgrades to the matching high-contrast variant when prefers-contrast:more; <meta theme-color> mapped per theme; re-resolves on OS color-scheme AND contrast changes while on system.
- Validation allowlists extended to accept the two HC values: User::theme_or_system, post_appearance, and the lc-theme cookie-sync in resolve_locale.
- Settings Appearance picker gains the two options; theme-hc-light / theme-hc-dark labels added to en + es main.ftl.

No new migration (reuses users.theme). just test + just test-saas green; cargo fmt --all clean; i18n_catalog gate passes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
nrupard deleted branch feat/lc-192-high-contrast 2026-05-27 21:09:08 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!238
No description provided.