Move dark mode toggle from sidebar to Settings > Display

This commit is contained in:
bobban committed 2026-09-19 01:56:08 +02:00
1 parent 5c35080e22
commit 4ba86429d5
2 files changed
+31 -18

No files matched your search

-18
View File
@@ -18,11 +18,8 @@ import {
IconStethoscope, IconStethoscope,
IconSettings, IconSettings,
IconMenu2, IconMenu2,
IconSun,
IconMoon,
} from "@tabler/icons-react"; } from "@tabler/icons-react";
import type { CurrentUser } from "../api/client"; import type { CurrentUser } from "../api/client";
import { getTheme, setTheme, type Theme } from "../utils/theme";
interface NavItem { interface NavItem {
to: string; to: string;
@@ -54,17 +51,10 @@ const roleRank: Record<CurrentUser["role"], number> = { viewer: 0, operator: 1,
export default function AppShell({ user, children }: { user: CurrentUser; children: ReactNode }) { export default function AppShell({ user, children }: { user: CurrentUser; children: ReactNode }) {
const [sidebarOpen, setSidebarOpen] = useState(false); const [sidebarOpen, setSidebarOpen] = useState(false);
const [theme, setThemeState] = useState<Theme>(() => getTheme());
const visibleItems = NAV_ITEMS.filter( const visibleItems = NAV_ITEMS.filter(
(item) => !item.minRole || roleRank[user.role] >= roleRank[item.minRole], (item) => !item.minRole || roleRank[user.role] >= roleRank[item.minRole],
); );
function toggleTheme() {
const next: Theme = theme === "dark" ? "light" : "dark";
setTheme(next);
setThemeState(next);
}
return ( return (
<div className="page"> <div className="page">
<aside className="navbar navbar-vertical navbar-expand-lg" data-bs-theme="dark"> <aside className="navbar navbar-vertical navbar-expand-lg" data-bs-theme="dark">
@@ -97,14 +87,6 @@ export default function AppShell({ user, children }: { user: CurrentUser; childr
))} ))}
</ul> </ul>
<div className="navbar-footer px-3"> <div className="navbar-footer px-3">
<button
type="button"
className="btn btn-outline-secondary btn-sm w-100 mb-2 d-flex align-items-center justify-content-center gap-2"
onClick={toggleTheme}
>
{theme === "dark" ? <IconSun size={16} /> : <IconMoon size={16} />}
{theme === "dark" ? "Light mode" : "Dark mode"}
</button>
<div className="text-secondary small mb-2"> <div className="text-secondary small mb-2">
Signed in as {user.name ?? user.email ?? user.sub} · {user.role} Signed in as {user.name ?? user.email ?? user.sub} · {user.role}
</div> </div>
@@ -1,7 +1,9 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { IconMoon, IconSun } from "@tabler/icons-react";
import { api, type AppSettings, type DateFormat, type TimeFormat } from "../../api/client"; import { api, type AppSettings, type DateFormat, type TimeFormat } from "../../api/client";
import { setDateTimeSettings } from "../../utils/date"; import { setDateTimeSettings } from "../../utils/date";
import { setPageSize } from "../../utils/pageSize"; import { setPageSize } from "../../utils/pageSize";
import { getTheme, setTheme, type Theme } from "../../utils/theme";
const DATE_FORMAT_OPTIONS: { value: DateFormat; label: string; example: string }[] = [ const DATE_FORMAT_OPTIONS: { value: DateFormat; label: string; example: string }[] = [
{ value: "ymd", label: "Year-Month-Day", example: "2026-09-15" }, { value: "ymd", label: "Year-Month-Day", example: "2026-09-15" },
@@ -19,10 +21,17 @@ export default function DisplaySettings() {
const [dateFormat, setDateFormatState] = useState<DateFormat>("ymd"); const [dateFormat, setDateFormatState] = useState<DateFormat>("ymd");
const [timeFormat, setTimeFormatState] = useState<TimeFormat>("24h"); const [timeFormat, setTimeFormatState] = useState<TimeFormat>("24h");
const [pageSize, setPageSizeState] = useState(20); const [pageSize, setPageSizeState] = useState(20);
const [theme, setThemeState] = useState<Theme>(() => getTheme());
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
const [saved, setSaved] = useState(false); const [saved, setSaved] = useState(false);
const [saveError, setSaveError] = useState<string | null>(null); const [saveError, setSaveError] = useState<string | null>(null);
function toggleTheme() {
const next: Theme = theme === "dark" ? "light" : "dark";
setTheme(next);
setThemeState(next);
}
useEffect(() => { useEffect(() => {
api.settings api.settings
.get() .get()
@@ -136,6 +145,28 @@ export default function DisplaySettings() {
</div> </div>
</div> </div>
</div> </div>
<div className="col-md-5">
<div className="card h-100">
<div className="card-header">
<h3 className="card-title">Theme</h3>
</div>
<div className="card-body">
<p className="text-secondary">
A personal preference remembered on this browser only — it doesn't affect other signed-in
users.
</p>
<button
type="button"
className="btn btn-outline-secondary d-flex align-items-center gap-2"
onClick={toggleTheme}
>
{theme === "dark" ? <IconSun size={16} /> : <IconMoon size={16} />}
Switch to {theme === "dark" ? "light" : "dark"} mode
</button>
</div>
</div>
</div>
</div> </div>
</> </>
); );