Skip to content

Form input borders fail WCAG SC 1.4.11 (3:1 non-text contrast) #27

@MaxGhenis

Description

@MaxGhenis

Problem

--input (and --border, which it tracks) is too light against --background to meet WCAG 2.2 SC 1.4.11 (Non-text Contrast, AA). The 3:1 minimum applies to UI component visual cues like form-field boundaries — without it, sighted-but-low-vision users can't tell a form input from the surrounding surface.

Computed ratios:

Mode --input vs --background Ratio Threshold Status
Light #E2E8F0 #FFFFFF 1.23:1 3:1 ❌ fail
Dark #334155 #0B0E14 1.87:1 3:1 ❌ fail

(The dark value is post-#26 — even after that PR's bump from #1E293B to #334155, it's still under 3:1 against --background. PR #26 brought it to 1.57:1 vs --card and 1.87:1 vs --background, both perceptible but neither meets the SC 1.4.11 floor.)

Why it matters

"Visual information required to identify user interface components and states, except for inactive components or where the appearance of the component is determined by the user agent and not modified by the author, has a contrast ratio of at least 3:1 against adjacent color(s)."
WCAG 2.2 SC 1.4.11

Form inputs are the canonical example.

Suggested fix

Either:

  1. Pin a darker --border-medium-style value to --input (e.g. #94A3B8 light gives 2.54:1 — still under 3:1; need closer to #6B7280 slate-500 ≈ 3.86:1) and pick a corresponding dark value (probably #475569 slate-600), then update the contrast matrix in src/theme/tokens.ts:contrastPairs to assert 3:1 in both modes.
  2. Or accept a different --input token that's separate from --border (which can stay decorative-only) and pin only --input at the higher-contrast value.

Either path needs a visual review against shadcn/ui's default field aesthetic — the higher-contrast borders feel "older" but are mandatory for AA.

Out-of-scope discovery

Surfaced during the round-1 adversarial review of #25 / round-2 of #26. Not introduced by either PR — pre-existing from the original shadcn-default token migration. Filing here so it doesn't get lost.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions