Dark/light mode added + switcher

This commit is contained in:
2026-04-13 17:47:46 +02:00
parent 602f0d16ee
commit 279422b02e
7 changed files with 87 additions and 34 deletions
+10 -10
View File
@@ -1,12 +1,12 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>aramjonghu-site</title>
</head>
<body class="bg-ctp-base">
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>aramjonghu-site</title>
</head>
<body class="bg-ctp-base">
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
+1 -1
View File
@@ -9,7 +9,7 @@ export default function Footer() {
};
return (
<footer className="flex items-center justify-between px-24 py-6 border-t border-ctp-lavender-800 mt-10">
<footer className="bg-ctp-mantle flex items-center justify-between px-24 py-6 border-t border-ctp-lavender-800 mt-10">
<p className="text-sm text-ctp-text">
&copy; {currentYear} AramJonghu. All rights reserved.
</p>
+18 -22
View File
@@ -1,27 +1,14 @@
import Aku from "../assets/images/aku.png";
export default function Header() {
export default function Header({ theme }) {
const { theme: currentTheme, toggleTheme } = theme;
const navItems = [
{
label: "Nextcloud",
url: "https://aramjonghu.nl/nextcloud",
},
{
label: "Navidrome",
url: "https://music.aramjonghu.nl",
},
{
label: "Forgejo Git",
url: "https://git.aramjonghu.nl",
},
{
label: "Stream",
url: "https://stream.aramjonghu.nl",
},
{
label: "SearXNG",
url: "https://xng.aramjonghu.nl",
},
{ label: "Nextcloud", url: "https://aramjonghu.nl/nextcloud" },
{ label: "Navidrome", url: "https://music.aramjonghu.nl" },
{ label: "Forgejo Git", url: "https://git.aramjonghu.nl" },
{ label: "Stream", url: "https://stream.aramjonghu.nl" },
{ label: "SearXNG", url: "https://xng.aramjonghu.nl" },
];
const goHome = () => {
@@ -29,7 +16,7 @@ export default function Header() {
};
return (
<header className="flex justify-center items-center px-12 py-6 gap-6 border-b border-ctp-lavender-800">
<header className="bg-ctp-mantle flex justify-between items-center px-12 py-6 gap-6 border-b border-ctp-lavender-800">
<img
className="size-16 cursor-pointer"
src={Aku}
@@ -48,6 +35,15 @@ export default function Header() {
</a>
))}
</nav>
<div>
<button
className="text-ctp-text hover:text-ctp-green-900 border rounded border-ctp-white-800 hover:border-ctp-green-900 cursor-pointer px-3 py-1"
onClick={toggleTheme}
>
{currentTheme === "macchiato" ? "🌙 Dark" : "☀️ Light"}
</button>
</div>
</header>
);
}
+4 -1
View File
@@ -1,10 +1,13 @@
import Footer from "./Footer";
import Header from "./Header";
import { useTheme } from "../hooks/useTheme";
export default function Layout({ children }) {
const theme = useTheme();
return (
<div className="flex flex-col w-screen min-h-screen bg-ctp-base">
<Header />
<Header theme={theme} />
<main className="flex-1">{children}</main>
<Footer />
</div>
+16
View File
@@ -0,0 +1,16 @@
import { useEffect, useState } from "react";
import { getInitialTheme, applyTheme, toggleTheme } from "../utils/theme";
export function useTheme() {
const [theme, setTheme] = useState(getInitialTheme);
useEffect(() => {
applyTheme(theme);
}, [theme]);
const handleToggle = () => {
setTheme((prev) => toggleTheme(prev));
};
return { theme, toggleTheme: handleToggle };
}
+30
View File
@@ -0,0 +1,30 @@
const LIGHT = "latte";
const DARK = "macchiato";
export function getSystemTheme() {
return window.matchMedia("(prefers-color-scheme: dark)").matches
? DARK
: LIGHT;
}
export function getStoredTheme() {
return localStorage.getItem("theme");
}
export function getInitialTheme() {
return getStoredTheme() || getSystemTheme();
}
export function applyTheme(theme) {
const root = document.documentElement;
root.classList.remove(LIGHT, DARK);
root.classList.add(theme);
localStorage.setItem("theme", theme);
}
export function toggleTheme(current) {
return current === DARK ? LIGHT : DARK;
}
+8
View File
@@ -0,0 +1,8 @@
export default {
darkMode: "class",
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};