From 9d8690623f3a1a5bf42cee5c5523cc0a1e160413 Mon Sep 17 00:00:00 2001 From: tariknz Date: Tue, 24 Jun 2025 21:00:25 +1200 Subject: [PATCH 1/4] add black theme --- .../ThemeManager/ThemeManager.stories.tsx | 139 +++++++++++------- .../components/ThemeManager/ThemeManager.tsx | 16 +- src/frontend/theme.css | 14 ++ src/types/dashboardLayout.ts | 1 + 4 files changed, 111 insertions(+), 59 deletions(-) diff --git a/src/frontend/components/ThemeManager/ThemeManager.stories.tsx b/src/frontend/components/ThemeManager/ThemeManager.stories.tsx index 7504452..8365710 100644 --- a/src/frontend/components/ThemeManager/ThemeManager.stories.tsx +++ b/src/frontend/components/ThemeManager/ThemeManager.stories.tsx @@ -19,20 +19,23 @@ export default meta; const createMockBridge = ( fontSize: 'xs' | 'sm' | 'lg' | 'xl', setFontSize: (size: 'xs' | 'sm' | 'lg' | 'xl') => void, + colorPalette: 'default' | 'black', + setColorPalette: (palette: 'default' | 'black') => void, widgets: DashboardLayout['widgets'] = [] ): DashboardBridge => ({ reloadDashboard: () => { // noop }, saveDashboard: (dashboard: DashboardLayout) => { - // Update the font size in the dashboard + // Update the font size and color palette in the dashboard setFontSize(dashboard.generalSettings?.fontSize || 'sm'); + setColorPalette((dashboard.generalSettings?.colorPalette as 'default' | 'black') || 'default'); }, dashboardUpdated: (callback) => { - // Initialize with current font size + // Initialize with current font size and color palette callback({ widgets, - generalSettings: { fontSize }, + generalSettings: { fontSize, colorPalette }, }); return () => { // noop @@ -49,13 +52,14 @@ const createMockBridge = ( resetDashboard: () => Promise.resolve({ widgets: [], - generalSettings: { fontSize }, + generalSettings: { fontSize, colorPalette }, }), }); -// Helper function to create font size buttons -const createFontSizeButtons = ( +// Helper function to create theme controls (font size buttons and color palette dropdown) +const createThemeControls = ( fontSize: 'xs' | 'sm' | 'lg' | 'xl', + colorPalette: 'default' | 'black', mockBridge: DashboardBridge ) => { const getButtonClass = (size: 'xs' | 'sm' | 'lg' | 'xl') => { @@ -66,51 +70,72 @@ const createFontSizeButtons = ( }; return ( -
- - - - +
+
+ + + + +
+
+ + +
); }; @@ -143,15 +168,16 @@ export const Primary = { export const WithFontSizeControls = { render: () => { const [fontSize, setFontSize] = useState<'xs' | 'sm' | 'lg' | 'xl'>('sm'); - const mockBridge = createMockBridge(fontSize, setFontSize); + const [colorPalette, setColorPalette] = useState<'default' | 'black'>('default'); + const mockBridge = createMockBridge(fontSize, setFontSize, colorPalette, setColorPalette); return (
- {createFontSizeButtons(fontSize, mockBridge)} -
+ {createThemeControls(fontSize, colorPalette, mockBridge)} +
This is extra small text
This is small text
This is base text
@@ -169,14 +195,15 @@ export const WithFontSizeControls = { export const WithAllAvailableWidgets = { render: () => { const [fontSize, setFontSize] = useState<'xs' | 'sm' | 'lg' | 'xl'>('sm'); - const mockBridge = createMockBridge(fontSize, setFontSize, defaultDashboard.widgets); + const [colorPalette, setColorPalette] = useState<'default' | 'black'>('default'); + const mockBridge = createMockBridge(fontSize, setFontSize, colorPalette, setColorPalette, defaultDashboard.widgets); return (
- {createFontSizeButtons(fontSize, mockBridge)} + {createThemeControls(fontSize, colorPalette, mockBridge)}

diff --git a/src/frontend/components/ThemeManager/ThemeManager.tsx b/src/frontend/components/ThemeManager/ThemeManager.tsx index 1cc5c4c..2749353 100644 --- a/src/frontend/components/ThemeManager/ThemeManager.tsx +++ b/src/frontend/components/ThemeManager/ThemeManager.tsx @@ -3,14 +3,24 @@ import { useGeneralSettings } from '@irdashies/context'; import { useLocation } from 'react-router-dom'; export const ThemeManager = ({ children }: PropsWithChildren) => { - const { fontSize } = useGeneralSettings() || {}; + const { fontSize, colorPalette } = useGeneralSettings() || {}; const location = useLocation(); - // Don't apply theme changes to the settings page since + // Don't apply theme changes to the settings page since // they share the same theme as the rest of the overlays if (location.pathname.startsWith('/settings')) { return <>{children}; } - return
{children}
; + return ( +
+ {children} +
+ ); }; diff --git a/src/frontend/theme.css b/src/frontend/theme.css index 508aaa9..63a9360 100644 --- a/src/frontend/theme.css +++ b/src/frontend/theme.css @@ -61,3 +61,17 @@ html { --text-lg: 20px; --text-xl: 22px; } + +.overlay-window.overlay-theme-color-black { + --color-slate-50: oklch(0.98 0 0); + --color-slate-100: oklch(0.95 0 0); + --color-slate-200: oklch(0.9 0 0); + --color-slate-300: oklch(0.8 0 0); + --color-slate-400: oklch(0.65 0 0); + --color-slate-500: oklch(0.5 0 0); + --color-slate-600: oklch(0.4 0 0); + --color-slate-700: oklch(0.3 0 0); + --color-slate-800: oklch(0.2 0 0); + --color-slate-900: oklch(0.1 0 0); + --color-slate-950: oklch(0.05 0 0); +} \ No newline at end of file diff --git a/src/types/dashboardLayout.ts b/src/types/dashboardLayout.ts index 267c2b3..59082b9 100644 --- a/src/types/dashboardLayout.ts +++ b/src/types/dashboardLayout.ts @@ -25,6 +25,7 @@ export interface DashboardWidget { export interface GeneralSettingsType { fontSize?: 'xs' | 'sm' | 'lg' | 'xl'; + colorPalette?: 'default' | string; } export interface DashboardLayout { From 334b3b44d5f6515f9bdf00f567aeaef7199033d3 Mon Sep 17 00:00:00 2001 From: tariknz Date: Wed, 25 Jun 2025 07:16:24 +1200 Subject: [PATCH 2/4] add the setting for changing the theme --- .../Settings/sections/GeneralSettings.tsx | 34 +++++++++++++++++++ .../ThemeManager/ThemeManager.stories.tsx | 14 ++++---- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/frontend/components/Settings/sections/GeneralSettings.tsx b/src/frontend/components/Settings/sections/GeneralSettings.tsx index 6af16dd..94211d7 100644 --- a/src/frontend/components/Settings/sections/GeneralSettings.tsx +++ b/src/frontend/components/Settings/sections/GeneralSettings.tsx @@ -9,10 +9,16 @@ const FONT_SIZE_PRESETS = { xl: 'Extra Large', }; +const COLOR_THEME_PRESETS = { + default: 'Slate (default)', + black: 'Black', +}; + export const GeneralSettings = () => { const { currentDashboard, onDashboardUpdated } = useDashboard(); const [settings, setSettings] = useState({ fontSize: currentDashboard?.generalSettings?.fontSize ?? 'sm', + colorPalette: currentDashboard?.generalSettings?.colorPalette ?? 'default', }); if (!currentDashboard || !onDashboardUpdated) { @@ -33,6 +39,12 @@ export const GeneralSettings = () => { updateDashboard(newSettings); }; + const handleColorThemeChange = (newTheme: 'default' | 'black') => { + const newSettings = { ...settings, colorPalette: newTheme }; + setSettings(newSettings); + updateDashboard(newSettings); + }; + return (
@@ -93,6 +105,28 @@ export const GeneralSettings = () => {
+ + {/* Color Theme Settings */} +
+
+

Color Theme

+
+ {COLOR_THEME_PRESETS[settings.colorPalette as keyof typeof COLOR_THEME_PRESETS ?? 'default']} +
+
+ + {/* Color Theme Dropdown */} +
+ +
+
); }; \ No newline at end of file diff --git a/src/frontend/components/ThemeManager/ThemeManager.stories.tsx b/src/frontend/components/ThemeManager/ThemeManager.stories.tsx index 8365710..7ce8902 100644 --- a/src/frontend/components/ThemeManager/ThemeManager.stories.tsx +++ b/src/frontend/components/ThemeManager/ThemeManager.stories.tsx @@ -19,8 +19,8 @@ export default meta; const createMockBridge = ( fontSize: 'xs' | 'sm' | 'lg' | 'xl', setFontSize: (size: 'xs' | 'sm' | 'lg' | 'xl') => void, - colorPalette: 'default' | 'black', - setColorPalette: (palette: 'default' | 'black') => void, + colorPalette: 'default' | string, + setColorPalette: (palette: 'default' | string) => void, widgets: DashboardLayout['widgets'] = [] ): DashboardBridge => ({ reloadDashboard: () => { @@ -29,7 +29,7 @@ const createMockBridge = ( saveDashboard: (dashboard: DashboardLayout) => { // Update the font size and color palette in the dashboard setFontSize(dashboard.generalSettings?.fontSize || 'sm'); - setColorPalette((dashboard.generalSettings?.colorPalette as 'default' | 'black') || 'default'); + setColorPalette(dashboard.generalSettings?.colorPalette || 'default'); }, dashboardUpdated: (callback) => { // Initialize with current font size and color palette @@ -59,7 +59,7 @@ const createMockBridge = ( // Helper function to create theme controls (font size buttons and color palette dropdown) const createThemeControls = ( fontSize: 'xs' | 'sm' | 'lg' | 'xl', - colorPalette: 'default' | 'black', + colorPalette: 'default' | string, mockBridge: DashboardBridge ) => { const getButtonClass = (size: 'xs' | 'sm' | 'lg' | 'xl') => { @@ -127,7 +127,7 @@ const createThemeControls = ( onChange={(e) => mockBridge.saveDashboard({ widgets: [], - generalSettings: { fontSize, colorPalette: e.target.value as 'default' | 'black' }, + generalSettings: { fontSize, colorPalette: e.target.value as 'default' | string }, }) } className="px-2 py-1 rounded border text-[12px]" @@ -168,7 +168,7 @@ export const Primary = { export const WithFontSizeControls = { render: () => { const [fontSize, setFontSize] = useState<'xs' | 'sm' | 'lg' | 'xl'>('sm'); - const [colorPalette, setColorPalette] = useState<'default' | 'black'>('default'); + const [colorPalette, setColorPalette] = useState<'default' | string>('default'); const mockBridge = createMockBridge(fontSize, setFontSize, colorPalette, setColorPalette); return ( @@ -195,7 +195,7 @@ export const WithFontSizeControls = { export const WithAllAvailableWidgets = { render: () => { const [fontSize, setFontSize] = useState<'xs' | 'sm' | 'lg' | 'xl'>('sm'); - const [colorPalette, setColorPalette] = useState<'default' | 'black'>('default'); + const [colorPalette, setColorPalette] = useState<'default' | string>('default'); const mockBridge = createMockBridge(fontSize, setFontSize, colorPalette, setColorPalette, defaultDashboard.widgets); return ( From 796a33afac8f5059611274bd8f04f856c3bbb170 Mon Sep 17 00:00:00 2001 From: tariknz Date: Wed, 25 Jun 2025 20:32:33 +1200 Subject: [PATCH 3/4] tidy up --- src/app/storage/defaultDashboard.ts | 1 + src/frontend/components/Settings/sections/GeneralSettings.tsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/storage/defaultDashboard.ts b/src/app/storage/defaultDashboard.ts index b7ed5d4..5bc53f5 100644 --- a/src/app/storage/defaultDashboard.ts +++ b/src/app/storage/defaultDashboard.ts @@ -92,5 +92,6 @@ export const defaultDashboard: DashboardLayout = { ], generalSettings: { fontSize: 'sm', + colorPalette: 'default', }, }; diff --git a/src/frontend/components/Settings/sections/GeneralSettings.tsx b/src/frontend/components/Settings/sections/GeneralSettings.tsx index 94211d7..d144bbc 100644 --- a/src/frontend/components/Settings/sections/GeneralSettings.tsx +++ b/src/frontend/components/Settings/sections/GeneralSettings.tsx @@ -9,7 +9,7 @@ const FONT_SIZE_PRESETS = { xl: 'Extra Large', }; -const COLOR_THEME_PRESETS = { +const COLOR_THEME_PRESETS: Record = { default: 'Slate (default)', black: 'Black', }; @@ -111,7 +111,7 @@ export const GeneralSettings = () => {

Color Theme

- {COLOR_THEME_PRESETS[settings.colorPalette as keyof typeof COLOR_THEME_PRESETS ?? 'default']} + {COLOR_THEME_PRESETS[settings.colorPalette ?? 'default']}
From 3421a21e3fa3cc179f36bfa64e9723675eee3663 Mon Sep 17 00:00:00 2001 From: tariknz Date: Wed, 25 Jun 2025 20:40:35 +1200 Subject: [PATCH 4/4] fix tests --- src/app/storage/dashboards.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/storage/dashboards.spec.ts b/src/app/storage/dashboards.spec.ts index c8ab440..1f54bd4 100644 --- a/src/app/storage/dashboards.spec.ts +++ b/src/app/storage/dashboards.spec.ts @@ -97,7 +97,7 @@ describe('dashboards', () => { it('should update an existing dashboard', () => { const existingDashboards = { default: defaultDashboard }; - const updatedDashboard: DashboardLayout = { widgets: [], generalSettings: { fontSize: 'lg' }}; + const updatedDashboard: DashboardLayout = { widgets: [], generalSettings: { fontSize: 'lg', colorPalette: 'black' }}; mockReadData.mockReturnValue(existingDashboards); saveDashboard('default', updatedDashboard); @@ -247,7 +247,7 @@ describe('dashboards', () => { const updatedDashboard = getOrCreateDefaultDashboard(); - expect(updatedDashboard.generalSettings).toEqual({ fontSize: 'sm' }); + expect(updatedDashboard.generalSettings).toEqual({ fontSize: 'sm', colorPalette: 'default' }); }); it('should preserve general settings from the existing dashboard', () => { @@ -258,7 +258,7 @@ describe('dashboards', () => { const updatedDashboard = getOrCreateDefaultDashboard(); - expect(updatedDashboard.generalSettings).toEqual({ fontSize: 'lg' }); + expect(updatedDashboard.generalSettings).toEqual({ fontSize: 'lg', colorPalette: 'default' }); }); }); });