diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 4a466702f..8301b73d9 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -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 = () => { + + + {/* Account Menu */} +
{ diff --git a/src/components/ThemeToggle.tsx b/src/components/ThemeToggle.tsx new file mode 100644 index 000000000..14d694c6e --- /dev/null +++ b/src/components/ThemeToggle.tsx @@ -0,0 +1,22 @@ +import { useTheme } from "@/context/ThemeContext"; +import { Sun, Moon } from "lucide-react"; + +const ThemeToggle = () => { + const { theme, toggleTheme } = useTheme(); + + return ( + + ); +}; + +export default ThemeToggle; diff --git a/src/context/ThemeContext.tsx b/src/context/ThemeContext.tsx new file mode 100644 index 000000000..680e837ce --- /dev/null +++ b/src/context/ThemeContext.tsx @@ -0,0 +1,40 @@ +import { createContext, useContext, useEffect, useState } from "react"; + +type Theme = "light" | "dark"; + +interface ThemeContextType { + theme: Theme; + toggleTheme: () => void; +} + +const ThemeContext = createContext({ + theme: "light", + toggleTheme: () => {}, +}); + +export const ThemeProvider = ({ children }: { children: React.ReactNode }) => { + const [theme, setTheme] = useState("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 ( + + {children} + + ); +}; + +export const useTheme = () => useContext(ThemeContext); diff --git a/src/layout/Layout.tsx b/src/layout/Layout.tsx index 6b008c4ce..31e2a74de 100644 --- a/src/layout/Layout.tsx +++ b/src/layout/Layout.tsx @@ -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 ( -
- -
{children}
-
-
- ); - }; - - export default Layout; \ No newline at end of file + 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 ( +
+ +
{children}
+
+
+ ); +}; + +export default Layout; diff --git a/src/main.tsx b/src/main.tsx index c7fe1b841..b1bbccfda 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -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( + @@ -89,5 +92,6 @@ ReactDOM.createRoot(document.getElementById("root")!).render( + ); \ No newline at end of file