Skip to content

feat: accessibility improvements, high contrast mode, i18n audit#139

Open
thedavidweng wants to merge 3 commits into
mainfrom
feat/issue-61-accessibility-i18n
Open

feat: accessibility improvements, high contrast mode, i18n audit#139
thedavidweng wants to merge 3 commits into
mainfrom
feat/issue-61-accessibility-i18n

Conversation

@thedavidweng

@thedavidweng thedavidweng commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Summary

Accessibility

  • Add aria-describedby on all form inputs to associate validation errors with their fields (prompt, lyrics, duration, bpm, negative prompt, inference steps, guidance scale)
  • Add aria-expanded to Collapsible and FailedRunsDrawer toggle buttons
  • Improve --color-text-dimmer contrast: #7a7a82 to #8a8a8e (light), #6f7780 to #858d96 (dark), #66666d to #808087 (darker) — meets WCAG AA

High contrast mode

  • Add highContrast store state + setHighContrast action
  • Add toggle in Settings > General
  • Add [data-high-contrast] CSS that raises --color-text-dim and --color-text-dimmer for users who need stronger contrast
  • Toggle applies data-high-contrast attribute on <html> via useEffect

i18n audit

  • Remove all defaultValue fallbacks from t() calls in settings sections, SetupScreen, LogsSection, NetworkActivitySection — every string now goes through the locale files
  • Add missing keys: noNetworkActivity, networkTime, networkMethod, networkUrl, networkStatus, anonymousErrorReports(+Description), downloadedBadge, shortcutsHint, shortcut_{toggleSidebar,newGeneration,toggleSettings,submitGeneration,togglePlayback}
  • Add zh-CN translations for all new keys
  • Add ja-JP/ko-KR feasibility notes in i18n.ts

Closes #61

Test plan

  • pnpm typecheck clean
  • pnpm lint clean
  • pnpm format:check clean
  • pnpm test:run (957 passed)

Generated with Devin


Open in Devin Review

@codecov

codecov Bot commented Jul 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.00000% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.9%. Comparing base (144d847) to head (59c6e2d).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...components/generation/GenerationPanel/FormBody.tsx 28.5% 0 Missing and 5 partials ⚠️
src/app/lib/store/slices/ui.ts 0.0% 3 Missing ⚠️
...pp/components/settings/sections/BackendSection.tsx 0.0% 2 Missing ⚠️
src/app/components/settings/SettingsOverlay.tsx 0.0% 1 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff          @@
##            main    #139   +/-   ##
=====================================
  Coverage   71.9%   71.9%           
=====================================
  Files         61      61           
  Lines       2389    2407   +18     
  Branches     710     720   +10     
=====================================
+ Hits        1719    1732   +13     
- Misses       476     479    +3     
- Partials     194     196    +2     
Flag Coverage Δ
frontend 71.9% <50.0%> (+<0.1%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
frontend 71.9% <50.0%> (+<0.1%) ⬆️
rust ∅ <ø> (∅)
Files with missing lines Coverage Δ
src/app/components/generation/GenerationPanel.tsx 55.4% <100.0%> (+0.2%) ⬆️
...p/components/generation/GenerationPanel/shared.tsx 61.1% <100.0%> (ø)
src/app/components/history/HistorySidebar.tsx 42.6% <ø> (+2.0%) ⬆️
src/app/components/settings/SetupScreen.tsx 70.3% <ø> (ø)
...pp/components/settings/sections/GeneralSection.tsx 70.0% <100.0%> (+5.2%) ⬆️
...c/app/components/settings/sections/LogsSection.tsx 74.1% <100.0%> (ø)
...nents/settings/sections/NetworkActivitySection.tsx 72.0% <100.0%> (ø)
src/app/components/ui/Collapsible.tsx 86.6% <ø> (ø)
src/app/lib/store/slices/settings.ts 100.0% <100.0%> (ø)
src/app/components/settings/SettingsOverlay.tsx 68.6% <0.0%> (ø)
... and 3 more
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@greptile-apps

greptile-apps Bot commented Jul 5, 2026

Copy link
Copy Markdown

Greptile Summary

This PR improves accessibility, adds a high-contrast mode, and audits i18n coverage across settings and setup screens. All previously flagged issues (persistence of high contrast, wrong "Ready" badge text) have been addressed in the latest commits.

  • Accessibility: aria-describedby wired to FieldError ids on all form inputs; aria-expanded added to Collapsible and FailedRunsDrawer toggle buttons; --color-text-dimmer contrast bumped across all three theme tiers.
  • High contrast mode: Full round-trip implemented — Rust settings model, TypeScript store slice with api.setSetting, hydration on startup, CSS [data-high-contrast] selector, and Settings UI toggle, with two new test cases.
  • i18n audit: All 14 defaultValue fallbacks replaced with proper locale keys; keys added to both en.json and zh-CN.json; setup.engineReady correctly distinguishes the engine "Ready" badge from the pack "Downloaded" badge.

Confidence Score: 5/5

Safe to merge — the changes are well-scoped accessibility and i18n improvements with correct persistence of the new high contrast preference.

The high contrast round-trip (Rust model → hydration → Zustand → CSS → UI toggle) is correctly implemented end-to-end, previously flagged issues with the "Ready" badge text and missing persistence have been fixed, all new i18n keys are present in both locale files, and accessibility attributes follow established patterns throughout the form.

No files require special attention.

Important Files Changed

Filename Overview
src-tauri/src/models/settings.rs Adds high_contrast: bool to AppSettings struct, SettingKey enum, and setter/serializer — mirrors the exact pattern of check_for_updates with no deviations.
src/app/App.tsx Adds useHighContrast hook that syncs the data-high-contrast attribute on <html> via useEffect; correctly depends on [highContrast] and useEffect is already imported.
src/app/lib/store/slices/ui.ts Adds highContrast state and setHighContrast action; persists via api.setSetting gated on isTauriRuntime(), consistent with the fix noted in the previous review thread.
src/app/lib/store/slices/settings.ts Hydrates highContrast from persisted settings on startup using mergedSettings.highContrast ?? false, correctly wiring persistence round-trip.
src/styles/globals.css Bumps --color-text-dimmer contrast values across all three theme tiers; adds [data-high-contrast] selector inside @layer base — declared after the [data-window-shell-tier] selectors so it correctly wins specificity conflicts when both attributes are on <html>.
src/app/components/generation/GenerationPanel/FormBody.tsx Adds aria-describedby to all seven form inputs; negativePrompt always references the stable description paragraph (desc-tweak-sound), other fields reference error ids only when errors exist — correct pattern.
src/app/components/settings/SetupScreen.tsx Removes all defaultValue fallbacks; correctly uses the new setup.engineReady key for the backend "Ready" badge and setup.downloadedBadge for the pack badge, resolving the previously flagged wrong-text issue.
src/locales/en.json Adds all 14 new keys removed from defaultValue fallbacks (engineReady, downloadedBadge, shortcutsHint, five shortcut_* keys, networkActivity*, anonymousErrorReports*, highContrast*) — complete coverage.
src/locales/zh-CN.json Adds zh-CN translations for all 14 new keys in parallel with en.json; translations appear idiomatic.
src/app/components/settings/sections/GeneralSection.tsx Adds high contrast checkbox wired to highContrast store state and setHighContrast action; two new tests added covering toggle and reflected-state scenarios.
tests/unit/settings-sections.test.tsx Adds highContrast: false and setHighContrast: vi.fn() to mock store; adds two new test cases for the high contrast toggle; updates text queries from hardcoded strings to i18n key strings.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[App startup / hydrateFromPersistence] -->|reads mergedSettings.highContrast| B[Zustand store\nhighContrast state]
    B --> C[useHighContrast hook\nin App.tsx]
    C -->|useEffect| D[document.documentElement\n.toggleAttribute\n'data-high-contrast']
    D --> E["CSS [data-high-contrast]\n--color-text-dim: #bbbbc0\n--color-text-dimmer: #9e9ea3"]

    F[GeneralSection\nhigh contrast checkbox] -->|onChange| G[setHighContrast action]
    G --> B
    G -->|isTauriRuntime| H[api.setSetting\n'highContrast', enabled]
    H --> I[Rust AppSettings\nhigh_contrast field\npersisted to disk]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[App startup / hydrateFromPersistence] -->|reads mergedSettings.highContrast| B[Zustand store\nhighContrast state]
    B --> C[useHighContrast hook\nin App.tsx]
    C -->|useEffect| D[document.documentElement\n.toggleAttribute\n'data-high-contrast']
    D --> E["CSS [data-high-contrast]\n--color-text-dim: #bbbbc0\n--color-text-dimmer: #9e9ea3"]

    F[GeneralSection\nhigh contrast checkbox] -->|onChange| G[setHighContrast action]
    G --> B
    G -->|isTauriRuntime| H[api.setSetting\n'highContrast', enabled]
    H --> I[Rust AppSettings\nhigh_contrast field\npersisted to disk]
Loading

Reviews (3): Last reviewed commit: "fix: add HighContrast backend setting ke..." | Re-trigger Greptile

Comment thread src/app/lib/store/slices/ui.ts
Comment thread src/app/components/settings/sections/GeneralSection.tsx
thedavidweng added a commit that referenced this pull request Jul 5, 2026
- Add setup.engineReady i18n key for backend engine badge (was showing "Pack downloaded")
- Persist highContrast preference via api.setSetting and load on hydration
- Add tests for high contrast toggle in GeneralSection

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
thedavidweng added a commit that referenced this pull request Jul 6, 2026
The frontend setHighContrast calls api.setSetting("highContrast", ...)
but the Rust SettingKey enum had no HighContrast variant, so parse()
returned a validation error and the preference was never persisted.

Add HighContrast to SettingKey, AppSettings.high_contrast, parse(),
as_str(), apply_setting(), entries(), and the known-keys test. The
setting now round-trips through SQLite and loads on hydration.

Addresses Greptile P1 review comment on #139.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
thedavidweng and others added 3 commits July 7, 2026 21:44
Accessibility:
- Add aria-describedby on all form inputs to associate validation
  errors with their fields (prompt, lyrics, duration, bpm, negative
  prompt, inference steps, guidance scale)
- Add aria-expanded to Collapsible and FailedRunsDrawer toggle buttons
- Improve --color-text-dimmer contrast: #7a7a82 → #8a8a8e (light),
  #6f7780 → #858d96 (dark), #66666d → #808087 (darker) — meets WCAG AA

High contrast mode:
- Add highContrast store state + setHighContrast action
- Add toggle in Settings > General
- Add [data-high-contrast] CSS that raises --color-text-dim and
  --color-text-dimmer for users who need stronger contrast
- Toggle applies data-high-contrast attribute on <html> via useEffect

i18n audit:
- Remove all defaultValue fallbacks from t() calls in settings sections,
  SetupScreen, LogsSection, NetworkActivitySection — every string now
  goes through the locale files
- Add missing keys: noNetworkActivity, networkTime, networkMethod,
  networkUrl, networkStatus, anonymousErrorReports(+Description),
  downloadedBadge, shortcutsHint, shortcut_{toggleSidebar,newGeneration,
  toggleSettings,submitGeneration,togglePlayback}
- Add zh-CN translations for all new keys
- Add ja-JP/ko-KR feasibility notes in i18n.ts

Tests updated to assert on i18n keys instead of defaultValue strings.

Closes #61

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Add setup.engineReady i18n key for backend engine badge (was showing "Pack downloaded")
- Persist highContrast preference via api.setSetting and load on hydration
- Add tests for high contrast toggle in GeneralSection

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The frontend setHighContrast calls api.setSetting("highContrast", ...)
but the Rust SettingKey enum had no HighContrast variant, so parse()
returned a validation error and the preference was never persisted.

Add HighContrast to SettingKey, AppSettings.high_contrast, parse(),
as_str(), apply_setting(), entries(), and the known-keys test. The
setting now round-trips through SQLite and loads on hydration.

Addresses Greptile P1 review comment on #139.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@thedavidweng thedavidweng force-pushed the feat/issue-61-accessibility-i18n branch from 59c6e2d to 0782c6b Compare July 8, 2026 04:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Accessibility & i18n: high contrast, aria attributes, ja-JP/ko-KR

1 participant