Skip to content

Conversation

@thc1006
Copy link

@thc1006 thc1006 commented Jan 10, 2026

Description

This PR adds Accessibility Theme Preferences to Relationship Menu:

  • High contrast toggle
  • Color-vision-deficiency (CVD) friendly themes:
    • Protanopia/Deuteranopia-friendly
    • Tritanopia-friendly
  • Preferences apply immediately and persist via localStorage.

Related discussion: #DISCUSSION_LINK
Closes #ISSUE_NUMBER

Problem / Motivation

The app currently supports light/dark mode, but lacks:

  • a high-contrast option for low-vision users
  • CVD-friendly palettes
  • guarantees that key UI states are not conveyed by color alone

This can make it harder to distinguish states like selected/active/focus or emphasis.

Changes

  • Theme system supports composition:
    • color mode: light | dark
    • vision: default | pd | tritan
    • contrast: normal | high
  • Added settings UI (radio buttons + contrast switch)
  • Added non-color cues for key states (e.g., icon/underline/border change)
  • Persisted settings to localStorage with a namespaced key: relationshipMenu.theme

Steps to Test

  1. npm install
  2. npm run dev
  3. Open the app and go to Settings → Theme preferences
  4. Verify:
    • Switching vision mode changes palette
    • Toggle “Increase contrast” increases contrast in UI elements and focus ring
    • Preferences persist after refresh
    • Keyboard navigation works and focus ring is clearly visible

Expected Behavior

  • Text contrast targets WCAG: normal text ≥ 4.5:1
  • Non-text UI components (buttons/inputs/focus indicators/icons conveying meaning) ≥ 3:1
  • No important meaning conveyed by color alone

Actual Behavior (Before)

  • Only light/dark mode
  • No high-contrast / CVD-friendly themes
  • Some states rely heavily on color differences

Environment

  • OS:
  • Browser:
  • Accessibility settings (if any): (e.g., Windows High Contrast / system increased contrast)

Screenshots / Screen recordings

Before After

Accessibility Notes

  • When no explicit preference is set, the UI respects system preferences when available:
    • prefers-color-scheme
    • prefers-contrast
    • forced-colors (should remain usable)

Risks / Rollback

  • Low risk: change is isolated to theming + settings UI
  • Rollback: revert commits; localStorage key will be ignored by older versions

Checklist

  • Self-reviewed code
  • UI changes have screenshots
  • Keyboard navigation verified
  • Contrast checks done (text and non-text)
  • No color-only cues for important states
  • Docs updated (if needed)

Co-authored-by: Paul-Vincent Roll paviro@me.com

Add user-facing theme settings for color vision accessibility and
high contrast mode, similar to GitHub's accessibility theming.

Features:
- Color mode selection: System / Light / Dark
- Vision themes: Default / Protanopia & Deuteranopia / Tritanopia
- High contrast toggle for enhanced visibility
- Preferences persist in localStorage
- FOUC prevention via inline script
- Full keyboard accessibility

Technical:
- Theme applied via data attributes on <html>
- CSS variables for all color combinations
- Respects prefers-color-scheme media query
- Forced colors mode support (Windows High Contrast)

Testing:
- 27 Playwright E2E tests covering all functionality
- Tests for persistence, accessibility, and CSS application

Co-authored-by: Paul-Vincent Roll <paviro@me.com>
Copilot AI review requested due to automatic review settings January 10, 2026 06:19
@thc1006 thc1006 changed the title feat(theme): add accessibility theme preferences feat(a11y): add high-contrast + CVD theme preferences Jan 10, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds comprehensive accessibility theme preferences to the application, allowing users to customize color modes, vision-specific color palettes, and contrast levels. The implementation includes robust E2E testing, FOUC prevention, and full keyboard navigation support.

Changes:

  • Added user-facing theme settings modal with color mode (System/Light/Dark), vision themes (Default/Protanopia & Deuteranopia/Tritanopia), and high contrast toggle
  • Implemented theme persistence via localStorage with validation and error handling
  • Created comprehensive E2E test suite with 27 tests covering all theme functionality

Reviewed changes

Copilot reviewed 10 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
playwright.config.ts Adds Playwright configuration for E2E testing with CI optimizations
package.json Adds @playwright/test dependency and test scripts
package-lock.json Updates lock file with Playwright packages
e2e/theme-settings.spec.ts Comprehensive E2E tests covering modal behavior, theme persistence, keyboard navigation, and accessibility
app/utils/themeStorage.ts Utility functions for reading/saving theme preferences with validation and system preference detection
app/types.ts Type definitions for theme preferences (ColorMode, VisionTheme, ContrastLevel)
app/components/ThemeProvider.tsx React context provider managing theme state and applying changes to DOM
app/components/ui/SettingsModal.tsx Settings modal component with radio groups for color mode/vision and toggle for contrast
app/components/Footer.tsx Adds Settings button to footer for opening theme modal
app/layout.tsx Adds inline script for FOUC prevention and ThemeProvider wrapper
app/globals.css Extensive CSS variables for all theme combinations, high contrast mode, forced colors support
.gitignore Adds Playwright output directories to gitignore

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Add prefers-contrast auto-detection (respects system high contrast)
- Add prefers-reduced-motion support to disable animations
- Configure Tailwind darkMode to use data-color-mode attribute
- Add aria-describedby to all radio inputs and contrast switch
- Add aria-label to contrast switch button
- Add browser fallback for prefers-contrast: high (earlier draft)
- Fix JSON.parse error handling for corrupted localStorage

All 27 E2E tests passing.

Co-authored-by: Paul-Vincent Roll <paviro@me.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 13 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Add listener for both prefers-contrast: more and high for consistency
- Extract hasExplicitContrastPreference() helper to avoid duplicate code
- Increase focus ring offset to 4px in high contrast mode for better visibility
- Use systemPrefersHighContrast() in listener for consistent detection logic

All 27 E2E tests passing.

Co-authored-by: Paul-Vincent Roll <paviro@me.com>
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.

1 participant