Add dark mode support with persisted OS-aware theme selection
This commit is contained in:
@@ -28,11 +28,14 @@ import {
|
||||
ListRegular,
|
||||
SignOutRegular,
|
||||
NavigationRegular,
|
||||
WeatherMoonRegular,
|
||||
WeatherSunnyRegular,
|
||||
} from "@fluentui/react-icons";
|
||||
import { NavLink, Outlet, useNavigate } from "react-router-dom";
|
||||
import { useAuth } from "../hooks/useAuth";
|
||||
import { useServerStatus } from "../hooks/useServerStatus";
|
||||
import { useBlocklistStatus } from "../hooks/useBlocklist";
|
||||
import { useThemeMode } from "../providers/ThemeProvider";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Styles
|
||||
@@ -146,11 +149,20 @@ const useStyles = makeStyles({
|
||||
padding: tokens.spacingVerticalS,
|
||||
flexShrink: 0,
|
||||
},
|
||||
footerActions: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: tokens.spacingVerticalXS,
|
||||
},
|
||||
themeButton: {
|
||||
width: "100%",
|
||||
justifyContent: "flex-start",
|
||||
},
|
||||
logoutButton: {
|
||||
width: "100%",
|
||||
justifyContent: "flex-start",
|
||||
},
|
||||
logoutButtonCollapsed: {
|
||||
sidebarButtonCollapsed: {
|
||||
justifyContent: "center",
|
||||
},
|
||||
versionText: {
|
||||
@@ -220,6 +232,7 @@ const NAV_ITEMS: NavItem[] = [
|
||||
export function MainLayout(): React.JSX.Element {
|
||||
const styles = useStyles();
|
||||
const { logout } = useAuth();
|
||||
const { colorMode, toggleColorMode } = useThemeMode();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const readSavedCollapsed = (): boolean => {
|
||||
@@ -346,31 +359,51 @@ export function MainLayout(): React.JSX.Element {
|
||||
})}
|
||||
</ul>
|
||||
|
||||
{/* Footer — Logout */}
|
||||
{/* Footer — Theme toggle and logout */}
|
||||
<div className={styles.sidebarFooter}>
|
||||
{!collapsed && (
|
||||
<Text className={styles.versionText}>
|
||||
BanGUI
|
||||
</Text>
|
||||
)}
|
||||
<Tooltip
|
||||
content={collapsed ? "Sign out" : ""}
|
||||
relationship="label"
|
||||
positioning="after"
|
||||
>
|
||||
<Button
|
||||
appearance="subtle"
|
||||
icon={<SignOutRegular />}
|
||||
onClick={() => void handleLogout()}
|
||||
aria-label="Sign out"
|
||||
className={mergeClasses(
|
||||
styles.logoutButton,
|
||||
collapsed && styles.logoutButtonCollapsed,
|
||||
)}
|
||||
<div className={styles.footerActions}>
|
||||
<Tooltip
|
||||
content={collapsed ? (colorMode === "dark" ? "Switch to light mode" : "Switch to dark mode") : ""}
|
||||
relationship="label"
|
||||
positioning="after"
|
||||
>
|
||||
{!collapsed && "Sign out"}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
appearance="subtle"
|
||||
icon={colorMode === "dark" ? <WeatherSunnyRegular /> : <WeatherMoonRegular />}
|
||||
onClick={toggleColorMode}
|
||||
aria-label={colorMode === "dark" ? "Switch to light mode" : "Switch to dark mode"}
|
||||
className={mergeClasses(
|
||||
styles.themeButton,
|
||||
collapsed && styles.sidebarButtonCollapsed,
|
||||
)}
|
||||
>
|
||||
{!collapsed && (colorMode === "dark" ? "Light mode" : "Dark mode")}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
content={collapsed ? "Sign out" : ""}
|
||||
relationship="label"
|
||||
positioning="after"
|
||||
>
|
||||
<Button
|
||||
appearance="subtle"
|
||||
icon={<SignOutRegular />}
|
||||
onClick={() => void handleLogout()}
|
||||
aria-label="Sign out"
|
||||
className={mergeClasses(
|
||||
styles.logoutButton,
|
||||
collapsed && styles.sidebarButtonCollapsed,
|
||||
)}
|
||||
>
|
||||
{!collapsed && "Sign out"}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user