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 { Menu, X, Volleyball, ChevronDown, Users } from "lucide-react";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAuth } from '@/context/AuthContext'; import { useAuth } from '@/context/AuthContext';
import axios from 'axios'; import ThemeToggle from './ThemeToggle';
type Team = { type Team = {
@ -93,6 +93,10 @@ const Navbar = () => {
</Button> </Button>
</Link> </Link>
<ThemeToggle />
{/* Account Menu */}
<div <div
className="relative ml-4" className="relative ml-4"
onMouseEnter={() => { 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,12 +1,23 @@
import { ReactNode, useEffect } from "react";
import Navbar from "@/components/Navbar"; import Navbar from "@/components/Navbar";
import Footer from "@/components/Footer"; import Footer from "@/components/Footer";
import { ReactNode } from "react"; import AOS from "aos";
import "aos/dist/aos.css";
type LayoutProps = { type LayoutProps = {
children: ReactNode; 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",
});
}, []);
const Layout = ({ children }: LayoutProps) => {
return ( return (
<div className="min-h-screen bg-white flex flex-col"> <div className="min-h-screen bg-white flex flex-col">
<Navbar /> <Navbar />
@ -14,6 +25,6 @@ type LayoutProps = {
<Footer /> <Footer />
</div> </div>
); );
}; };
export default Layout; export default Layout;

View File

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