Adds a persistent dark/light theme toggle (localStorage + data-bs-theme on <html>) so it applies globally, including the circuit editor route which has no visible sidebar. An inline beforeInteractive script sets the theme before hydration to avoid a flash of the wrong theme. Bootstrap components pick up data-bs-theme automatically; the custom circuit-grid CSS previously used ~150 hardcoded hex colors, all converted to semantic tokens in globals.css with light/dark values. Verified with a headless-browser pass across the project list, project detail page, circuit editor, project-device drawer and a settings modal in both themes; no console errors. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
import type { Metadata } from "next";
|
|
import Script from "next/script";
|
|
import "bootstrap/dist/css/bootstrap.min.css";
|
|
import "./globals.css";
|
|
import { AppShell } from "../frontend/components/AppShell";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Leistungsbilanz",
|
|
description: "Leistungsbilanz für elektrische Verbraucher und Stromkreislisten",
|
|
};
|
|
|
|
// Keep this key literal in sync with THEME_STORAGE_KEY in ThemeToggle.tsx.
|
|
// It must stay inline (not imported) so it runs before hydration and never
|
|
// flashes the wrong theme on load.
|
|
const THEME_INIT_SCRIPT = `
|
|
(function () {
|
|
try {
|
|
var stored = localStorage.getItem("leistungsbilanz:theme");
|
|
var theme =
|
|
stored === "dark" || stored === "light"
|
|
? stored
|
|
: window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
? "dark"
|
|
: "light";
|
|
document.documentElement.setAttribute("data-bs-theme", theme);
|
|
} catch (error) {
|
|
// Storage/matchMedia unavailable: fall back to the default light theme.
|
|
}
|
|
})();
|
|
`;
|
|
|
|
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
|
|
return (
|
|
<html lang="de" suppressHydrationWarning>
|
|
<body>
|
|
<Script id="theme-init" strategy="beforeInteractive">
|
|
{THEME_INIT_SCRIPT}
|
|
</Script>
|
|
<AppShell>{children}</AppShell>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|