Add theme switcher to MainMenu#13937
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
✅ PR preview is ready!
|
📉 Frontend coverage change detectedThe frontend unit test (vitest) coverage has decreased by 0.1400%
💡 Consider adding more unit tests to maintain or improve coverage. |
There was a problem hiding this comment.
Pull request overview
This PR adds a theme switcher directly to the MainMenu, allowing users to toggle between System, Light, and Dark themes using menuitemradio elements. This builds on the accessibility refactor from #13878 and provides a more convenient way to change themes without opening the Settings dialog (which will be deprecated in a future PR).
Changes:
- Added theme selection UI as three radio buttons (System, Light, Dark) at the top of the main menu
- Integrated theme switching with existing ThemeContext to maintain theme state
- Updated keyboard navigation to seamlessly flow between radio items and action items
- Radio items do not close the menu when selected, allowing users to preview themes
Reviewed changes
Copilot reviewed 6 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
frontend/app/src/components/MainMenu/themeSection.ts |
Pure logic for building theme section data structure from ThemeContext state |
frontend/app/src/components/MainMenu/themeSection.test.ts |
Comprehensive unit tests for theme section builder logic |
frontend/app/src/components/MainMenu/styled-components.ts |
Styled components for theme radio group and individual radio items |
frontend/app/src/components/MainMenu/MainMenu.tsx |
Integration of theme section into menu with discriminated unions and roving tabindex |
frontend/app/src/components/MainMenu/MainMenu.test.tsx |
Comprehensive unit tests for theme switcher integration in MainMenu |
e2e_playwright/main_menu_test.py |
E2E tests for keyboard navigation, theme persistence, and OS preference changes |
e2e_playwright/__snapshots__/* |
Updated visual snapshots for all browsers (Chromium, Firefox, WebKit) in both light and dark themes |
SummaryThis PR adds a theme switcher (System / Light / Dark) directly into the
Code QualityThe code quality is excellent and follows established patterns well:
One minor note on const hasCustomTheme = availableThemes.some(
theme =>
theme.name === CUSTOM_THEME_NAME || theme.name.startsWith("Custom Theme")
)The first clause ( Test CoverageTest coverage is thorough and well-structured across three layers: Unit tests (
Integration tests (
E2E tests (
Backwards CompatibilityNo breaking changes. The theme switcher is purely additive UI:
Security & RiskNo security concerns identified. The changes are entirely frontend UI:
AccessibilityAccessibility is a standout strength of this PR:
Recommendations
VerdictAPPROVED: This is a well-implemented, thoroughly tested, and accessibility-compliant addition of a theme switcher to the MainMenu. The code follows established patterns, introduces no breaking changes, and provides excellent coverage across unit, integration, and E2E tests. This is an automated AI review by |
| /** Theme selection options with their icons */ | ||
| type ThemeSelection = "System" | "Light" | "Dark" |
There was a problem hiding this comment.
suggestion: Please leverage the existing ThemeSelection type from frontend/lib/src/theme/types.ts, rather than redefining it here.
Adds a theme toggle (System / Light / Dark) directly into the main menu as `menuitemradio` elements, building on the accessibility refactor in #13878. **Changes:** - Three radio items (System, Light, Dark) appear at the top of the menu, inside a `role="group"` container with `aria-label="Theme"`. - Each item uses `role="menuitemradio"` with `aria-checked` to reflect the active theme. - Selecting a theme calls `setTheme` via `ThemeContext` without closing the menu, so users can preview different themes. - Keyboard navigation (ArrowUp/Down, Home/End, Enter/Space) flows seamlessly between radio items and action items in a single roving tabindex.
Adds a theme toggle (System / Light / Dark) directly into the main menu as `menuitemradio` elements, building on the accessibility refactor in #13878. **Changes:** - Three radio items (System, Light, Dark) appear at the top of the menu, inside a `role="group"` container with `aria-label="Theme"`. - Each item uses `role="menuitemradio"` with `aria-checked` to reflect the active theme. - Selecting a theme calls `setTheme` via `ThemeContext` without closing the menu, so users can preview different themes. - Keyboard navigation (ArrowUp/Down, Home/End, Enter/Space) flows seamlessly between radio items and action items in a single roving tabindex.
This PR is the culmination of the following PRs approved into this feature branch: - [Core `MainMenu` Refactor](#13833) - [`MainMenu` accessibility improvements](#13878) - [Add theme switcher to `MainMenu`](#13937) - [Add auto-rerun toggle to `MainMenu`](#13988) - [Add version footer to `MainMenu`](#14028) - [Remove `SettingsDialog`](#14048)
Describe your changes
Adds a theme toggle (System / Light / Dark) directly into the main menu as
menuitemradioelements, building on the accessibility refactor in #13878.Note: the Settings dialog's theme selection mechanism will be removed in a separate PR when the full
SettingsDialog& menu option is removed.Changes:
role="group"container witharia-label="Theme".role="menuitemradio"witharia-checkedto reflect the active theme.setThemeviaThemeContextwithout closing the menu, so users can preview different themes.Testing Plan