fix(ui): replace ANSI dim with explicit FG.faint colors; WCAG contrast fixes#2221
Conversation
esengine
left a comment
There was a problem hiding this comment.
The core change is a genuine accessibility win — replacing <Text dim> (SGR 2, which halves brightness and goes near-invisible on dark terminals) with explicit FG.faint across the UI, plus the WCAG-AA contrast bumps to fg.faint/fg.meta. That part I'm happy with (it does change existing themes' faint/meta values, but deliberately and for the better). The dim→FG.faint sweep across the 26 components is consistent and CI's green.
But the PR also bundles a more invasive, separate change with a real failure mode: setting the terminal's background via OSC 11 (\x1b]11;${themeBg}\x07) before render(), restored via OSC 111 only after await waitUntilExit().
- Restore isn't crash-safe. The OSC 111 restore only runs on a clean exit. If the process is SIGKILL'd, crashes, or exits on an unhandled signal, the restore never fires and the user's terminal is left repainted with the theme background — a bad state they have to fix manually. Please move the restore to
process.on("exit")plus SIGINT/SIGTERM handlers so it fires on every exit path. - Confirm it's intended / consider splitting. Overriding the user's terminal background is more than 'replace ANSI dim' implies — some users deliberately set their terminal bg. Either gate it (opt-in) or at least call it out; ideally it's its own PR separate from the a11y sweep.
The dim→faint + contrast work is ready; it's the OSC 11 terminal-bg override (crash-safety + intent) that I'd want resolved before merge.
… themes fg.faint failed WCAG on all 4 dark themes (ratios 1.63-2.56:1, need 4.5:1). fg.meta failed on midnight (2.35-2.91:1) and was borderline on others. Dark theme bgElev (#151d2f) was too close to bgInput for surface distinction. Changes per theme: - dark: meta #778294→#9aa5b5, faint #4d5666→#8791a3, bgElev #151d2f→#1c2844 - light: meta #6b7280→#5c6371, faint #9ca3af→#666d7b - midnight: meta #565f89→#9da5bb, faint #414868→#8a92a8 - deep-blue: meta #808080→#909090, faint #606060→#8c8c8c - high-contrast: already passes, no changes
- ReasoningCard: replace `dim` prop with explicit `FG.sub` color - ToolCard: replace conditional `dim` with explicit `FG.faint`/`errColor` Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace every remaining `dim` prop across 22 UI components with explicit
`color={FG.faint}` (or conditional color logic where dim was used as a
boolean toggle). The ANSI `dim` attribute (SGR 2) halves brightness of
the foreground color, causing near-invisible text on dark terminals
where the default foreground is already low-contrast.
Components fixed:
- mcp-browse, AtMentionSuggestions, DiffApp, EditConfirm
- McpBrowser, McpHub, McpMarketplace
- PlanReviseConfirm, PlanStepList
- RecordView, ReplayApp, Select, Setup
- SlashArgPicker, SlashSuggestions, SplitDiff
- StatsPanel, Wizard, char-bar, ctx-breakdown
- markdown-view (SpanText ambientDim), primitives (Bar, ContextCell)
For conditional dim (e.g. `dim={isDone}`), replaced with conditional
color logic (`color={isDone ? FG.faint : originalColor}`). The Bar
component's `dim` prop was removed entirely — callers now pass the
appropriate color directly.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
5154d2b to
3392895
Compare
|
Updated: the OSC 11 terminal background change has been split out to a separate PR (#2223) with crash-safe restore ( This PR now contains only:
|
esengine
left a comment
There was a problem hiding this comment.
Re-reviewed — you split the OSC 11 terminal-background change out to #2223 (0 OSC refs here now), so this PR is exactly the part I endorsed: the dim→FG.faint sweep across the UI plus the WCAG-AA contrast bumps to fg.faint/fg.meta. That's a clean accessibility win (SGR 2 dim is genuinely near-invisible on dark terminals), CI green. Merging.
Summary
Replace the ANSI
dimattribute (SGR 2) with explicitFG.faintcolor references across all UI components. Thedimattribute halves foreground brightness, producing near-invisible text on dark terminals where the default foreground is already low-contrast.Also fixes WCAG AA contrast ratios for
fg.faintandfg.metaacross all dark themes, and adds OSC 11 terminal background emission so iTerm and similar terminals inherit the theme's surface background.Extracted from #2171 (closed) — the background fix portion is handled separately by #2182.
Commits
tokens.tsfor dark, light, midnight, deep-blue themes to meet 4.5:1 contrast ratiodimprop withcolor={FG.faint}or conditional color logicFiles changed (26)
tokens.ts(WCAG),chat.tsx(OSC 11),ReasoningCard.tsx,ToolCard.tsx, plus 22 components with dim→FG.faint replacement.Test plan
dimprops in UI components🤖 Generated with Claude Code