From ff6792f5c203554929e76a223110a9f91c0d6049 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:37:08 +0000 Subject: [PATCH 1/3] Initial plan From f3d018e71a89e313ee21403273263abb0a04ea47 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:41:34 +0000 Subject: [PATCH 2/3] feat: add light/dark/system theme toggle in Settings (v1.2.6) Co-authored-by: CSfromCS <42040696+CSfromCS@users.noreply.github.com> --- package-lock.json | 4 +-- package.json | 2 +- src/App.tsx | 62 ++++++++++++++++++++++++++++++++++++++++++++++- src/index.css | 50 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4ce4d62..42e4ac9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "app", - "version": "1.1.44", + "version": "1.2.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "app", - "version": "1.1.44", + "version": "1.2.6", "dependencies": { "@fontsource-variable/plus-jakarta-sans": "^5.2.8", "@hookform/resolvers": "^5.2.2", diff --git a/package.json b/package.json index f5fa8db..e3b82a6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "app", "private": true, - "version": "1.2.5", + "version": "1.2.6", "type": "module", "scripts": { "dev": "vite", diff --git a/src/App.tsx b/src/App.tsx index 31001f8..14707a6 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -39,7 +39,9 @@ import { formatLabSingleReport, formatUrinalysis, } from './labFormatters' -import { Users, UserRound, Settings, HeartPulse, Pill, FlaskConical, ClipboardList, Camera, ChevronLeft, ChevronRight, CheckCircle2, Info, Download, Upload, Trash2 } from 'lucide-react' +import { Users, UserRound, Settings, HeartPulse, Pill, FlaskConical, ClipboardList, Camera, ChevronLeft, ChevronRight, CheckCircle2, Info, Download, Upload, Trash2, Sun, Moon, Monitor } from 'lucide-react' + +type Theme = 'light' | 'dark' | 'system' type PatientFormState = { roomNumber: string @@ -863,6 +865,37 @@ function App() { const [showOnboarding, setShowOnboarding] = useState(false) const onboardingAutoInstallAttemptedRef = useRef(false) const [deferredInstallPromptEvent, setDeferredInstallPromptEvent] = useState(null) + const [theme, setThemeState] = useState(() => { + const stored = localStorage.getItem('puhrr-theme') + return (stored === 'light' || stored === 'dark' || stored === 'system') ? stored : 'system' + }) + + const setTheme = useCallback((next: Theme) => { + localStorage.setItem('puhrr-theme', next) + setThemeState(next) + }, []) + + useEffect(() => { + const root = document.documentElement + const applyDark = (dark: boolean) => { + if (dark) root.classList.add('dark') + else root.classList.remove('dark') + } + if (theme === 'dark') { + applyDark(true) + return + } + if (theme === 'light') { + applyDark(false) + return + } + // system + const mq = window.matchMedia('(prefers-color-scheme: dark)') + applyDark(mq.matches) + const handler = (e: MediaQueryListEvent) => applyDark(e.matches) + mq.addEventListener('change', handler) + return () => mq.removeEventListener('change', handler) + }, [theme]) const canUseWebShare = typeof navigator !== 'undefined' && typeof navigator.share === 'function' const isStandaloneDisplayMode = useMemo(() => { if (typeof window === 'undefined') return false @@ -5001,6 +5034,33 @@ function App() {

App

+ {/* Theme */} +
+
+ {theme === 'dark' ? : theme === 'light' ? : } +
+
+

Appearance

+
+ {([['light', 'Light', Sun], ['dark', 'Dark', Moon], ['system', 'System', Monitor]] as [Theme, string, typeof Sun][]).map(([value, label, Icon]) => ( + + ))} +
+
+
- ))} -
-
-