Skip to content

FEAT use ThemeProvider instead of boolean for theme#1991

Open
hannahwestra25 wants to merge 3 commits into
microsoft:mainfrom
hannahwestra25:hannahwestra25/theming-redesign-exploration
Open

FEAT use ThemeProvider instead of boolean for theme#1991
hannahwestra25 wants to merge 3 commits into
microsoft:mainfrom
hannahwestra25:hannahwestra25/theming-redesign-exploration

Conversation

@hannahwestra25

@hannahwestra25 hannahwestra25 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

What

Replaces the prop-drilled isDarkMode boolean with a proper ThemeProvider + useTheme hook. The sidebar now has a 3-way picker (System / Light / Dark) instead of a single toggle, and the choice persists across reloads.

Why

The old setup had a few issues:

  • Theme state was hardcoded to dark and prop-drilled App → MainLayout → Navigation
  • No persistence — every reload reset to dark
  • No respect for OS preference
  • Violated the style guide rule about cross-cutting concerns living in src/hooks/

What's new

  • System mode follows prefers-color-scheme live (flip your OS theme, the app follows)
  • Light / Dark modes pin the choice
  • Choice persists to localStorage
  • data-theme + color-scheme written to <html> for any CSS that wants to react

Try it

Sidebar → sun/moon icon → pick a mode.

Easiest way to test System mode without changing OS settings: DevTools → Cmd/Ctrl+Shift+P → "Show Rendering" → toggle "Emulate CSS media feature prefers-color-scheme" between light/dark. With the picker on System, the app should flip live.

…rast

Replace prop-drilled isDarkMode state with a ThemeProvider/useTheme
context hook in src/hooks/ (matching the useConnectionHealth pattern
and the style guide's cross-cutting concern rule).

Behavior changes:
- Three-mode picker (System/Light/Dark) in the sidebar via a Fluent
  Menu/MenuItemRadio.
- 'System' follows prefers-color-scheme live.
- Selection persists to localStorage.
- forced-colors media query auto-applies Fluent's high-contrast theme
  regardless of mode, so OS HC users get a usable UI without a manual
  toggle.
- documentElement gets data-theme and color-scheme attributes for
  any CSS overrides.

Refactors:
- App.tsx, MainLayout.tsx, and Navigation.tsx no longer pass theme
  state around.
- main.tsx wraps App in <ThemeProvider> outside AuthProvider so theme
  applies during auth flows.

Tests:
- New useTheme.test.tsx covers resolver, persistence, live media
  query updates, document attribute writes, and localStorage failure
  modes.
- Navigation.test.tsx rewritten around the new menu picker.
- App.test.tsx and MainLayout.test.tsx updated to drop dropped theme
  props/tests and wrap with ThemeProvider where needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@hannahwestra25 hannahwestra25 changed the title FE Add ThemeProvider with System/Light/Dark picker and auto high-contrast FEAT use ThemeProvider instead of boolean for theme Jun 10, 2026
We don't actually QA the app in forced-colors mode and Fluent's HC
theme only covers Fluent components — claiming HC support set an
expectation we hadn't validated. HC users still get the browser's
default forced-colors fallback; if we want real HC support later it
should be a dedicated effort.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@hannahwestra25 hannahwestra25 marked this pull request as ready for review June 10, 2026 21:20
@romanlutz

Copy link
Copy Markdown
Contributor

So this would allow us to add more custom ones as well? Like a raccoon theme, or pirate theme, etc.?

@hannahwestra25

Copy link
Copy Markdown
Contributor Author

So this would allow us to add more custom ones as well? Like a raccoon theme, or pirate theme, etc.?

omg love the idea of a raccoon / pirate theme but yes! Adding another theme is basically:

  1. Add the name to ThemeMode (and ResolvedTheme if it's its own rendered theme).
  2. Add an entry to FLUENT_THEMES — Fluent's createLightTheme / createDarkTheme will generate a full ramp from a brand color, so a raccoon palette or a pirate palette is mostly just picking the brand ramp.
  3. Add it to the sidebar picker.

Two caveats worth flagging:

  • 'system' only resolves to light or dark, so custom themes would always be a pinned choice —unfortunately the OS can't pick "raccoon" for you (yet!!).

  • The current sidebar UI is a sun/moon button with a 3-way menu. Once we go beyond ~3 themes we'd probably want a proper dropdown / submenu instead.

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.

2 participants