mirror of
https://github.com/coder/coder.git
synced 2026-10-16 14:48:56 +08:00
The ring around each theme swatch in the Appearance settings (Theme mode set to "Sync with system") used the decorative border color: `#27272A` on the `#09090B` page, 1.33:1. The Dark default swatch is filled with the page color, so that ring is its only visible boundary, which fails WCAG 1.4.11 Non-text Contrast. The ring now uses the existing `surface-invert-secondary` token, which the Slider handle already uses for its border: `#A1A1AA` on the dark page (7.8:1) and `#3F3F46` on white (10.5:1). The blue selected and focus outline is unchanged. Fixes DEQ-597 ## Before and after Appearance > Theme mode "Sync with system", resting state. Dark default is the first swatch. | | Before | After | |---|---|---| | Dark page | <img width="360" src="https://raw.githubusercontent.com/coder/coder/assets/a11y-theme-swatch-contrast/dark-before.png" /> | <img width="360" src="https://raw.githubusercontent.com/coder/coder/3e8883931834186feab055d104b7c62fb352240d/dark-after.png" /> | | Light page | <img width="360" src="https://raw.githubusercontent.com/coder/coder/assets/a11y-theme-swatch-contrast/light-before.png" /> | <img width="360" src="https://raw.githubusercontent.com/coder/coder/3e8883931834186feab055d104b7c62fb352240d/light-after.png" /> | <details> <summary>Decision log</summary> - **Resting border, not a focus state.** 1.4.11 requires the control's boundary to be visible without interaction. The swatches already show a blue `content-link` outline when focused or selected, and the audit flagged the unselected, unfocused swatches. - **Existing token instead of a new one.** `surface-invert-secondary` already exists on `main` and is used as a control border by the Slider handle. It passes 3:1 in both modes. None of the existing `border-*` tokens do on the dark page (`border-secondary` is 1.9:1). - **Before images** were captured on the same dev server with the previous border value (`hsl(var(--border))`) applied through an injected style. Light-page images force the `light` class on `<html>`. </details> <details> <summary>Verification</summary> - Playwright on the dev server at `/settings/appearance`: the Dark default swatch's computed border is `rgb(161, 161, 170)` on the dark page (`rgb(9, 9, 11)`) and `rgb(63, 63, 70)` on the light page (`rgb(255, 255, 255)`). - `pnpm check` and `pnpm lint` pass. - vitest unit (`src/pages/UserSettingsPage`, `src/theme`): 13 files, 399 tests pass. </details> --- _Generated by Coder Agents on behalf of @chrifro._ --------- Co-authored-by: Andrew Aquino <dawneraq@gmail.com>