WIP: dark mode
This commit is contained in:
@@ -6,6 +6,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
|
|||||||
NEXT_PUBLIC_EXPORT_STATIC=false
|
NEXT_PUBLIC_EXPORT_STATIC=false
|
||||||
NEXT_PUBLIC_USE_CGI=false
|
NEXT_PUBLIC_USE_CGI=false
|
||||||
# App-Versionsnummer
|
# App-Versionsnummer
|
||||||
NEXT_PUBLIC_APP_VERSION=1.6.869
|
NEXT_PUBLIC_APP_VERSION=1.6.870
|
||||||
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)
|
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)
|
||||||
|
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ NEXT_PUBLIC_CPL_API_PATH=/CPL
|
|||||||
NEXT_PUBLIC_EXPORT_STATIC=true
|
NEXT_PUBLIC_EXPORT_STATIC=true
|
||||||
NEXT_PUBLIC_USE_CGI=true
|
NEXT_PUBLIC_USE_CGI=true
|
||||||
# App-Versionsnummer
|
# App-Versionsnummer
|
||||||
NEXT_PUBLIC_APP_VERSION=1.6.869
|
NEXT_PUBLIC_APP_VERSION=1.6.870
|
||||||
NEXT_PUBLIC_CPL_MODE=production
|
NEXT_PUBLIC_CPL_MODE=production
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
## [1.6.870] – 2025-09-08
|
||||||
|
|
||||||
|
- fix: Beim Aufruf der TDR-Detailseite erscheint im Hintergrund auf der KÜ ein Schleifenwiderstand von 0 KOhm. In der Daten Javascriptdatei steht jedoch der richtige Wert.
|
||||||
|
|
||||||
|
---
|
||||||
## [1.6.869] – 2025-09-08
|
## [1.6.869] – 2025-09-08
|
||||||
|
|
||||||
- fix: Beim Ausführen einer TDR-Messung (Klick auf blauen Button in der TDR-Detailseite) erscheint keine Rückmeldung. Dort müsste ein Hinweis erscheinen “TDR-Messung wird ausgeführt und kann bis zu zwei Minuten dauern”
|
- fix: Beim Ausführen einer TDR-Messung (Klick auf blauen Button in der TDR-Detailseite) erscheint keine Rückmeldung. Dort müsste ein Hinweis erscheinen “TDR-Messung wird ausgeführt und kann bis zu zwei Minuten dauern”
|
||||||
|
|||||||
@@ -109,19 +109,46 @@ function Header() {
|
|||||||
}, [deviceName, dispatch]);
|
}, [deviceName, dispatch]);
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
// Dark/Light Mode Toggle
|
// Dark/Light Mode Toggle (persist in localStorage)
|
||||||
const [isDark, setIsDark] = useState(false);
|
const [isDark, setIsDark] = useState<boolean>(() => {
|
||||||
useEffect(() => {
|
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
const html = document.documentElement;
|
return document.documentElement.classList.contains("dark");
|
||||||
if (isDark) {
|
}
|
||||||
html.classList.add("dark");
|
return false;
|
||||||
} else {
|
});
|
||||||
html.classList.remove("dark");
|
|
||||||
|
// Apply + persist when toggled
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof window === "undefined") return;
|
||||||
|
const html = document.documentElement;
|
||||||
|
if (isDark) {
|
||||||
|
html.classList.add("dark");
|
||||||
|
try {
|
||||||
|
localStorage.setItem("theme", "dark");
|
||||||
|
} catch {
|
||||||
|
/* ignore storage write errors */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
html.classList.remove("dark");
|
||||||
|
try {
|
||||||
|
localStorage.setItem("theme", "light");
|
||||||
|
} catch {
|
||||||
|
/* ignore storage write errors */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [isDark]);
|
}, [isDark]);
|
||||||
|
|
||||||
|
// Sync if another tab changes the theme
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = (e: StorageEvent) => {
|
||||||
|
if (e.key === "theme" && e.newValue) {
|
||||||
|
setIsDark(e.newValue === "dark");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener("storage", handler);
|
||||||
|
return () => window.removeEventListener("storage", handler);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="bg-gray-300 dark:bg-gray-800 flex justify-between items-center w-full h-[13vh] laptop:h-[10vh] relative text-black dark:text-white ">
|
<header className="bg-gray-300 dark:bg-gray-800 flex justify-between items-center w-full h-[13vh] laptop:h-[10vh] relative text-black dark:text-white ">
|
||||||
<div
|
<div
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "cpl-v4",
|
"name": "cpl-v4",
|
||||||
"version": "1.6.869",
|
"version": "1.6.870",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cpl-v4",
|
"name": "cpl-v4",
|
||||||
"version": "1.6.869",
|
"version": "1.6.870",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/roboto": "^5.1.0",
|
"@fontsource/roboto": "^5.1.0",
|
||||||
"@headlessui/react": "^2.2.4",
|
"@headlessui/react": "^2.2.4",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cpl-v4",
|
"name": "cpl-v4",
|
||||||
"version": "1.6.869",
|
"version": "1.6.870",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 3000",
|
"dev": "next dev -p 3000",
|
||||||
|
|||||||
@@ -1,15 +1,26 @@
|
|||||||
import { Html, Head, Main, NextScript } from "next/document";
|
import { Html, Head, Main, NextScript } from "next/document";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom Document to inject an early theme script so the dark-mode preference
|
||||||
|
* (stored in localStorage under key 'theme': 'dark' | 'light') is applied
|
||||||
|
* before the first paint. This verhindert ein "Flash" von Light-Mode beim
|
||||||
|
* Seitenwechsel / Reload in der statisch gebauten Produktion.
|
||||||
|
*/
|
||||||
export default function Document() {
|
export default function Document() {
|
||||||
|
const setThemeScript = `(()=>{try{const k='theme';const t=localStorage.getItem(k);const m=window.matchMedia('(prefers-color-scheme: dark)').matches;const useDark = t? t==='dark' : m;const c=document.documentElement.classList;useDark?c.add('dark'):c.remove('dark');}catch(e){/* ignore */}})();`;
|
||||||
return (
|
return (
|
||||||
<Html lang="de">
|
<Html lang="de">
|
||||||
<Head>
|
<Head>
|
||||||
{/* Füge Meta-Tags, CSS-Links und andere Header-Inhalte hier hinzu */}
|
|
||||||
<link rel="icon" href="/favicon.png" type="image/png" />
|
<link rel="icon" href="/favicon.png" type="image/png" />
|
||||||
|
{/* Early inline script (no external blocking) */}
|
||||||
|
<script
|
||||||
|
// eslint-disable-next-line react/no-danger
|
||||||
|
dangerouslySetInnerHTML={{ __html: setThemeScript }}
|
||||||
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
<body>
|
<body>
|
||||||
<Main /> {/* Hier wird der Seiteninhalt eingebettet */}
|
<Main />
|
||||||
<NextScript /> {/* Fügt Next.js-Skripte für die Seite hinzu */}
|
<NextScript />
|
||||||
</body>
|
</body>
|
||||||
</Html>
|
</Html>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user