Comprehensive design covering color system overhaul, component fixes, accessibility properties, keyboard navigation, and reduced motion support.
7.3 KiB
WCAG 2.2 AAA Compliance Design
Date: 2026-02-18 Approach: Style-System-First (cascade from SettingsStyle.qml, then per-component fixes) Goal: Full WCAG 2.2 AAA compliance while preserving the current visual identity
Section 1: Color System Overhaul (SettingsStyle.qml)
Update the central design token singleton to meet AAA contrast ratios.
| Token | Current | New | Rationale |
|---|---|---|---|
accentPurple |
#7000FF (1.6:1) |
#B794F6 (7.2:1) |
AAA normal text on #121212 |
textSecondary |
#999999 (6.3:1) |
#ABABAB (8.1:1) |
AAA normal text |
borderSubtle |
rgba(1,1,1,0.08) |
rgba(1,1,1,0.22) |
3:1 non-text contrast |
New tokens to add:
textDisabled: "#808080"(4.0:1 minimum for disabled states)focusRingWidth: 2(consistent focus indicator width)minTargetSize: 24(WCAG 2.5.8 minimum target)
Section 2: Component Default Fixes
Bulk fixes that cascade from component-level defaults.
ModernSlider.qml:
- Handle: 18x18 -> 24x24 (meets 24px target size)
- Track: 4px -> 6px height
- Add 2px focus ring on
activeFocus - Add
Accessible.role: Accessible.Slider
ModernSwitch.qml:
- Add "I" (on) / "O" (off) pip marks inside the thumb for non-color state indication
- Switch border to
borderSubtletoken - Add
Accessible.role: Accessible.CheckBoxwith state in name
ModernTextField.qml:
- Placeholder:
#606060->#808080(3.7:1 minimum) - Focus border: 1px -> 2px
- Add
Accessible.role: Accessible.EditableText
ModernComboBox.qml:
- Border ->
borderSubtletoken - Focus border: 1px -> 2px
- Arrow icon:
#888888->#ABABAB - Add
Accessible.role: Accessible.ComboBox
ModernKeySequenceRecorder.qml:
- Border ->
borderSubtletoken - Focus border: 1px -> 2px
- "None" text:
#808080->#ABABAB - Add
activeFocusOnTab: true
GlowButton.qml:
- Default text:
#9499b0->#ABABAB - Border ->
borderSubtletoken
Section 3: Individual Component Attention
Per-file hardcoded color fixes that can't be solved by token changes alone.
Settings.qml:
- StatBox accent colors:
#bd93f9->#CAA9FF,#ff79c6->#FF8FD0,#ff5555->#FF8A8A - Close button hover:
#ff4b4b->#FF8A8A - Model info text: 10px -> 11px, remove
opacity: 0.6 - INSTALLED tag: verify contrast of green-on-dark
Loader.qml:
- Subtitle:
#80ffffff->#ABABAB - Status text: remove
opacity: 0.8, use fulltextSecondary - Border:
#40ffffff->rgba(1,1,1,0.22)
Overlay.qml:
- Border:
#40ffffff->rgba(1,1,1,0.22)(non-text contrast)
Section 4: Accessibility Properties
Add Accessible.name and Accessible.role to every interactive and informational element.
Window-level:
- Overlay.qml:
Accessible.name: "WhisperVoice Overlay",title: "WhisperVoice" - Settings.qml:
Accessible.name: "WhisperVoice Settings",title: "WhisperVoice Settings" - Loader.qml:
Accessible.name: "WhisperVoice Loading",title: "WhisperVoice"
Overlay.qml elements:
- Mic button:
Accessible.name: ui.isRecording ? "Stop recording" : "Start recording",Accessible.role: Accessible.Button - Status text:
Accessible.name: statusText.text,Accessible.role: Accessible.AlertMessage - Transcription text:
Accessible.name: transcriptionText.text,Accessible.role: Accessible.StaticText
Settings.qml elements:
- Nav items:
Accessible.name: modelData,Accessible.role: Accessible.Tab - Close button:
Accessible.name: "Close settings",Accessible.role: Accessible.Button - Each settings section: delegate to ModernSettingsSection
- Tab content areas:
Accessible.role: Accessible.PageTab
Shared components:
- ModernSettingsSection:
Accessible.name: root.title + " settings group",Accessible.role: Accessible.Grouping - ModernSettingsItem:
Accessible.name: root.label,Accessible.role: Accessible.Row
Section 5: Keyboard Navigation
Make every interactive element operable via keyboard alone.
Overlay.qml mic button:
- Add
activeFocusOnTab: true - Add
Keys.onReturnPressed/Keys.onSpacePressed-> toggle recording - Add visible 2px focus ring using
activeFocusstate
Settings.qml nav sidebar:
- Add
activeFocusOnTab: trueto each nav item - Add
Keys.onReturnPressed/Keys.onSpacePressed-> select tab - Add
Keys.onUpPressed/Keys.onDownPressed-> move between tabs - Visible focus ring on each nav item
Settings.qml close button:
- Add
activeFocusOnTab: true - Add
Keys.onReturnPressed/Keys.onSpacePressed-> close
All custom controls:
- Ensure
activeFocusOnTab: trueon ModernSlider, ModernSwitch, ModernComboBox, ModernKeySequenceRecorder, GlowButton - 2px focus ring visible when
activeFocusis true
Section 6: Reduced Motion Support
Three-layer system: OS detection, user toggle, animation conditionals.
Config layer (config.py):
- Add
"reduce_motion": falseto DEFAULT_SETTINGS
OS detection (main.py):
- On Windows startup, call
SystemParametersInfo(SPI_GETCLIENTAREAANIMATION)via ctypes - If OS says reduce motion, set config
reduce_motion: true(user can override)
Bridge layer (bridge.py):
- Add
reduceMotionQ_PROPERTY (bool, notify signal) - Reads from config, exposed to QML as
ui.reduceMotion
QML conditionals:
Overlay.qml animations (6 total):
- Shimmer:
running: !ui.reduceMotion - Gradient blobs shader:
visible: !ui.reduceMotion, static fallback color - Glow shader:
visible: !ui.reduceMotion - CRT shader:
visible: !ui.reduceMotion - Particle emitter:
enabled: !ui.reduceMotion - Rainbow wave shader:
visible: !ui.reduceMotion
Loader.qml animations (2 total):
- Icon pulse:
running: !ui.reduceMotion - Progress shimmer:
running: !ui.reduceMotion
UI toggle:
- Add "Reduce Motion" toggle in Settings.qml Visuals tab
- Bound to config
reduce_motionvia bridge
Section 7: Remaining WCAG AAA Criteria
7a. Status Messages (4.1.3):
- Overlay status label gets
Accessible.role: Accessible.AlertMessage(covered in Section 4)
7b. Text Scaling (1.4.4, 1.4.10):
- Already handled by existing
ui_scaleconfig property. No changes needed.
7c. Page Titles (2.4.2):
- Window titles set in Section 4 window-level properties.
7d. Error Identification (3.3.1):
- Not applicable. No user-submitted forms with validation.
Files Changed (Summary)
| File | Changes |
|---|---|
src/ui/qml/SettingsStyle.qml |
Token updates + new tokens |
src/ui/qml/Overlay.qml |
Colors, accessibility, keyboard, reduced motion |
src/ui/qml/Settings.qml |
Colors, accessibility, keyboard, reduce motion toggle |
src/ui/qml/Loader.qml |
Colors, accessibility, reduced motion |
src/ui/qml/ModernSlider.qml |
Size, focus ring, accessibility |
src/ui/qml/ModernSwitch.qml |
I/O marks, border, accessibility |
src/ui/qml/ModernTextField.qml |
Placeholder color, focus, accessibility |
src/ui/qml/ModernComboBox.qml |
Border, arrow color, focus, accessibility |
src/ui/qml/ModernKeySequenceRecorder.qml |
Border, colors, focus, accessibility |
src/ui/qml/GlowButton.qml |
Text color, border, accessibility |
src/ui/qml/ModernSettingsSection.qml |
Accessibility properties |
src/ui/qml/ModernSettingsItem.qml |
Accessibility properties |
src/core/config.py |
Add reduce_motion default |
src/ui/bridge.py |
Add reduceMotion property |
main.py |
Windows reduced-motion OS detection |