From c8a33a06fa8643b708223d9eb6d66e877bacf092 Mon Sep 17 00:00:00 2001 From: blacksuan19 Date: Sun, 15 Mar 2026 20:18:51 -0500 Subject: [PATCH] feat(ui): add system theme mode for dark mode controls - default Joy color scheme to system - cycle theme control through light, dark, and system modes - update labels and icons to reflect the active theme preference Signed-off-by: blacksuan19 --- .../components/DarkModeToggleButton.tsx | 69 ++++++++++++++----- src/common/providers/ProviderTheming.tsx | 2 +- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/common/components/DarkModeToggleButton.tsx b/src/common/components/DarkModeToggleButton.tsx index 7ca93319d..60f010cad 100644 --- a/src/common/components/DarkModeToggleButton.tsx +++ b/src/common/components/DarkModeToggleButton.tsx @@ -1,8 +1,10 @@ import * as React from 'react'; import { Button, IconButton, useColorScheme } from '@mui/joy'; +import BrightnessAutoIcon from '@mui/icons-material/BrightnessAuto'; import DarkModeIcon from '@mui/icons-material/DarkMode'; import LightModeIcon from '@mui/icons-material/LightMode'; +import { GoodTooltip } from './GoodTooltip'; export const darkModeToggleButtonSx = { boxShadow: 'sm', @@ -12,29 +14,64 @@ export const darkModeToggleButtonSx = { }, } as const; +type ThemeMode = 'light' | 'dark' | 'system'; + +const _nextThemeMode: Record = { + light: 'dark', + dark: 'system', + system: 'light', +}; + +const _themeModeLabel: Record = { + light: 'Light Theme', + dark: 'Dark Theme', + system: 'System Theme', +}; + +function _themeModeIcon(mode: ThemeMode) { + switch (mode) { + case 'dark': + return ; + case 'system': + return ; + case 'light': + default: + return ; + } +} + export function DarkModeToggleButton(props: { hasText?: boolean }) { // external state const { mode: colorMode, setMode: setColorMode } = useColorScheme(); + const mode: ThemeMode = colorMode === 'light' || colorMode === 'dark' || colorMode === 'system' + ? colorMode + : 'system'; const handleToggleDarkMode = (event: React.MouseEvent) => { event.stopPropagation(); - setColorMode(colorMode === 'dark' ? 'light' : 'dark'); + setColorMode(_nextThemeMode[mode]); }; - return props.hasText ? ( - - ) : ( - - {colorMode !== 'dark' ? : } - + const title = `Theme: ${_themeModeLabel[mode]}`; + + return ( + + {props.hasText ? ( + + ) : ( + + {_themeModeIcon(mode)} + + )} + ); -} \ No newline at end of file +} diff --git a/src/common/providers/ProviderTheming.tsx b/src/common/providers/ProviderTheming.tsx index 1f75e185b..86b7e0b8b 100644 --- a/src/common/providers/ProviderTheming.tsx +++ b/src/common/providers/ProviderTheming.tsx @@ -61,7 +61,7 @@ export const ProviderTheming = (props: { emotionCache?: EmotionCache, children: return ( - + {/* Inject sprites to be referenced by SVG rendering */}