Skip to content

feat(ui): add UI text-size scaling and high-contrast mode#831

Merged
wesm merged 5 commits into
mainfrom
feat/ui-scaling-high-contrast
Jun 24, 2026
Merged

feat(ui): add UI text-size scaling and high-contrast mode#831
wesm merged 5 commits into
mainfrom
feat/ui-scaling-high-contrast

Conversation

@wesm

@wesm wesm commented Jun 24, 2026

Copy link
Copy Markdown
Member

Adds two Settings -> Appearance accessibility controls, both persisted in localStorage. Frontend-only.

Text size (90-130%)

A uniform UI scale that reuses the existing root-zoom mechanism: one effect sets document.documentElement.style.zoom to the font scale composed with the desktop window zoom -- (IS_DESKTOP ? zoomLevel/100 : 1) * (fontScale/100), rounded to 4 decimals. On the web only the font scale applies; on desktop the two multiply. agentsview-font-scale persists everywhere; the desktop agentsview-zoom-level stays desktop-only.

High contrast

A high-contrast root class (composing with light/dark) drives :root.high-contrast and :root.dark.high-contrast overrides of the neutral text/border tokens and --accent-blue, plus a strengthened focus ring. Every overridden token clears WCAG AA against the real backgrounds. The shell and the token-driven majority of the transcript are covered by the token overrides; the three literal-colored transcript components (CallGroup, SubagentCalls, CallRow) get colocated :global(.high-contrast) overrides. Data-visualization palettes and category identity colors (--cat-*) are left unchanged so their encoded meaning is preserved.

Where to look

  • frontend/src/lib/stores/ui.svelte.ts -- state, setters, the composed-zoom and high-contrast effects, and the persistence split.
  • frontend/src/app.css -- high-contrast token overrides and focus ring.
  • frontend/src/lib/components/settings/AppearanceSettings.svelte -- the controls.

Note

This branch and #821 both edit ui.svelte.ts in adjacent regions; whichever merges second may need a small conflict resolution.

@roborev-ci

roborev-ci Bot commented Jun 24, 2026

Copy link
Copy Markdown

roborev: Combined Review (5659a00)

No issues found.


Panel: ci_default_security | Synthesis: codex | Members: codex_default (claude-code/default, done, 2m37s), codex_security (claude-code/security, done, 58s) | Total: 3m35s

Add two Settings -> Appearance accessibility controls, both persisted in
localStorage:

- Text size (90-130%): a uniform UI scale applied as a composed root zoom
  on documentElement. On the web it scales by the font setting; on desktop
  it multiplies with the existing window zoom, rounded to 4 decimals.
- High contrast: a high-contrast root class driving :root.high-contrast and
  :root.dark.high-contrast overrides of the neutral text/border tokens plus
  a strengthened focus ring, raising the shell and transcript toward WCAG AA.
  Colocated overrides cover the literal-colored CallGroup, SubagentCalls, and
  CallRow transcript components. Data-visualization and category identity
  colors are left unchanged.
@wesm wesm force-pushed the feat/ui-scaling-high-contrast branch from 5659a00 to 61a097c Compare June 24, 2026 18:38
@wesm

wesm commented Jun 24, 2026

Copy link
Copy Markdown
Member Author

tested locally, will merge when CI green

@roborev-ci

roborev-ci Bot commented Jun 24, 2026

Copy link
Copy Markdown

roborev: Combined Review (61a097c)

Summary verdict: One medium contrast regression should be fixed before merging.

Medium

  • frontend/src/app.css:146 - Dark high-contrast mode sets --accent-blue to a light blue while that token is also used as a filled background for primary buttons and selection with color: white, making those controls low-contrast in a mode intended to improve readability.

    Fix: Split the link/focus accent from the filled-button accent, or add .dark.high-contrast overrides so accent-filled controls use a dark foreground or a darker accent background.


Panel: ci_default_security | Synthesis: codex, 6s | Members: codex_default (codex/default, done, 4m12s), codex_security (codex/security, done, 15s) | Total: 4m33s

Dark high-contrast mode intentionally lightens the link and focus accent, but filled controls reused that same accent with hard-coded white text. That made prominent actions and text selection lower contrast than the default theme in the accessibility mode.

Add a foreground token for accent-blue fills so dark themes can pair the light accent with dark text while preserving the existing accent color for links, focus rings, and visual identity.
@roborev-ci

roborev-ci Bot commented Jun 24, 2026

Copy link
Copy Markdown

roborev: Combined Review (fe29d03)

Changes need attention: one medium contrast regression remains.

Medium

  • frontend/src/app.css:148 - Dark high-contrast mode changes --accent-blue to a light blue, but some accent-filled labels still hardcode color: white while using var(--accent-blue) indirectly, including user role icons and Claude/unknown agent badges. These become low-contrast in the new mode. Use var(--accent-blue-foreground) for remaining accent-filled text consumers, or add foreground handling for dynamic agent/role colors.

Panel: ci_default_security | Synthesis: codex, 6s | Members: codex_default (codex/default, done, 4m18s), codex_security (codex/security, done, 14s) | Total: 4m38s

The accent foreground token fixed direct blue filled controls, but agent and role surfaces can receive the same blue through dynamic helpers and custom properties. In dark high-contrast mode those paths still paired the light blue fill with white text or icons.

Centralize the foreground decision for blue agent fills and pass it through the breadcrumb, message role icon, and filter checkmark surfaces so fallback and Claude-colored labels keep the same contrast guarantees as primary controls.
@roborev-ci

roborev-ci Bot commented Jun 24, 2026

Copy link
Copy Markdown

roborev: Combined Review (491272c)

Summary verdict: one medium contrast issue remains; no security issues were found.

Medium

  • frontend/src/lib/components/content/MessageContent.svelte:164, frontend/src/lib/utils/agents.ts:81
    Non-blue filled badges/icons still hard-code white foregrounds. In dark high-contrast mode, assistant role icons use dark-mode --accent-purple and agents such as codex use dark-mode --accent-green, both of which are light fills with poor contrast against #ffffff.

    Fix: Add foreground tokens or a color-to-foreground map for every filled accent color, then use it for role icons, agent badges, and selected agent checks. Add dark high-contrast coverage for a non-blue agent and assistant role icon.


Panel: ci_default_security | Synthesis: codex, 6s | Members: codex_default (codex/default, done, 3m48s), codex_security (codex/security, done, 32s) | Total: 4m26s

Dark high-contrast mode makes the accent palette light, so a blue-only foreground special case left purple, green, and other filled accent surfaces paired with white text. Role icons and dynamic agent badges need to derive foregrounds from the same accent contract as primary controls.

Define foreground tokens for the accent palette and route agent, role, and selected-filter foregrounds through those tokens so future accent-colored agents do not reintroduce the same contrast bug.
@roborev-ci

roborev-ci Bot commented Jun 24, 2026

Copy link
Copy Markdown

roborev: Combined Review (c5e1bda)

Medium contrast issue remains in one filled accent control; no security findings.

Medium

  • frontend/src/lib/components/insights/InsightsPage.svelte:1893 - .generate-action still uses background: var(--accent-purple) with color: white. In dark/high-contrast mode --accent-purple is a light fill, so white text remains low contrast despite the new high-contrast setting. Use the matching foreground token, such as color: var(--accent-purple-foreground), and extend contrast coverage to catch remaining hard-coded white/#fff on accent fills.

Panel: ci_default_security | Synthesis: codex, 8s | Members: codex_default (codex/default, done, 5m17s), codex_security (codex/security, done, 14s) | Total: 5m39s

Accent foreground tokens only help if filled controls actually use them. A few component-local accent fills still hard-coded white text, including the insights generate action, so dark high-contrast could still render low-contrast labels.

Add a component source guard for hard-coded white foregrounds on accent-filled styles and route the remaining offenders through the matching accent foreground tokens.
@roborev-ci

roborev-ci Bot commented Jun 24, 2026

Copy link
Copy Markdown

roborev: Combined Review (1afdaf9)

Verdict: No Medium, High, or Critical findings to report.

The only reported issue was Low severity and is omitted per the review-combination rules.


Panel: ci_default_security | Synthesis: codex, 5s | Members: codex_default (codex/default, done, 4m57s), codex_security (codex/security, done, 50s) | Total: 5m52s

@wesm wesm merged commit e65fe7a into main Jun 24, 2026
23 checks passed
@wesm wesm deleted the feat/ui-scaling-high-contrast branch June 24, 2026 20:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant