Basic dark mode implemented
Some checks failed
Deploy Volleyball Dev / deploy (push) Has been cancelled

This commit is contained in:
Marc Wieland 2025-05-16 18:59:59 +02:00
parent 50253f20fb
commit f35bae79bf
5 changed files with 97 additions and 16 deletions

View File

@ -3,7 +3,7 @@ import { Button } from "@/components/ui/button";
import { Menu, X, Volleyball, ChevronDown, Users } from "lucide-react";
import { Link, useNavigate } from "react-router-dom";
import { useAuth } from '@/context/AuthContext';
import axios from 'axios';
import ThemeToggle from './ThemeToggle';
type Team = {
@ -93,6 +93,10 @@ const Navbar = () => {
</Button>
</Link>
<ThemeToggle />
{/* Account Menu */}
<div
className="relative ml-4"
onMouseEnter={() => {

View File

@ -0,0 +1,22 @@
import { useTheme } from "@/context/ThemeContext";
import { Sun, Moon } from "lucide-react";
const ThemeToggle = () => {
const { theme, toggleTheme } = useTheme();
return (
<button
onClick={toggleTheme}
className="p-2 rounded-full bg-white dark:bg-gray-800 shadow-md hover:scale-105 transition flex items-center justify-center"
aria-label="Toggle Theme"
>
{theme === "dark" ? (
<Sun className="h-5 w-5 text-yellow-400" />
) : (
<Moon className="h-5 w-5 text-gray-600" />
)}
</button>
);
};
export default ThemeToggle;

View File

@ -0,0 +1,40 @@
import { createContext, useContext, useEffect, useState } from "react";
type Theme = "light" | "dark";
interface ThemeContextType {
theme: Theme;
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType>({
theme: "light",
toggleTheme: () => {},
});
export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
const [theme, setTheme] = useState<Theme>("light");
useEffect(() => {
const stored = localStorage.getItem("theme") as Theme | null;
const system = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
const initial = stored || system;
setTheme(initial);
document.documentElement.classList.toggle("dark", initial === "dark");
}, []);
const toggleTheme = () => {
const newTheme = theme === "dark" ? "light" : "dark";
setTheme(newTheme);
localStorage.setItem("theme", newTheme);
document.documentElement.classList.toggle("dark", newTheme === "dark");
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => useContext(ThemeContext);

View File

@ -1,19 +1,30 @@
import { ReactNode, useEffect } from "react";
import Navbar from "@/components/Navbar";
import Footer from "@/components/Footer";
import { ReactNode } from "react";
import AOS from "aos";
import "aos/dist/aos.css";
type LayoutProps = {
children: ReactNode;
};
const Layout = ({ children }: LayoutProps) => {
return (
<div className="min-h-screen bg-white flex flex-col">
<Navbar />
<main className="flex-1 pt-16">{children}</main>
<Footer />
</div>
);
};
export default Layout;
children: ReactNode;
};
const Layout = ({ children }: LayoutProps) => {
useEffect(() => {
AOS.init({
duration: 800, // Dauer der Animationen
once: true, // nur einmal pro Element
offset: 100, // wie weit gescrollt werden muss
easing: "ease-out-cubic",
});
}, []);
return (
<div className="min-h-screen bg-white flex flex-col">
<Navbar />
<main className="flex-1 pt-16">{children}</main>
<Footer />
</div>
);
};
export default Layout;

View File

@ -33,10 +33,13 @@ import Impressum from "./pages/Impressum";
import Satzung from "./pages/Satzung";
import Beitraege from "./pages/Beitraege";
import { ThemeProvider } from "@/context/ThemeContext";
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<ThemeProvider>
<BrowserRouter>
<AuthProvider>
<Routes>
@ -89,5 +92,6 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
</Routes>
</AuthProvider>
</BrowserRouter>
</ThemeProvider>
</React.StrictMode>
);