Skip to content

Commit

Permalink
dark mode button with icons
Browse files Browse the repository at this point in the history
  • Loading branch information
zouhelen committed Mar 4, 2025
1 parent 975844a commit fcab651
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 13 deletions.
40 changes: 40 additions & 0 deletions src/client/components/DarkButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from "react";

interface DarkButtonProps {
darkMode: boolean;
toggleDarkMode: () => void;
}

const DarkButton: React.FC<DarkButtonProps> = ({ darkMode, toggleDarkMode }) => {
return (
<button onClick={toggleDarkMode} className="rounded-lg p-2 hover:bg-gray-200 dark:hover:bg-gray-800">
{/* //{darkMode ? "Dark Mode is enabled" : "Light Mode is enabled"} */}
{darkMode ? (
// Dark Mode Icon
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path
fill="currentColor"
fillRule="evenodd"
d="M22 12c0 5.523-4.477 10-10 10a10 10 0 0 1-3.321-.564A9 9 0 0 1 8 18a8.97 8.97 0 0 1 2.138-5.824A6.5 6.5 0 0 0 15.5 15a6.5 6.5 0 0 0 5.567-3.143c.24-.396.933-.32.933.143"
clipRule="evenodd"
opacity="0.5"
/>
<path
fill="currentColor"
d="M2 12c0 4.359 2.789 8.066 6.679 9.435A9 9 0 0 1 8 18c0-2.221.805-4.254 2.138-5.824A6.47 6.47 0 0 1 9 8.5a6.5 6.5 0 0 1 3.143-5.567C12.54 2.693 12.463 2 12 2C6.477 2 2 6.477 2 12"
/>
</svg>
) : (
// Light Mode Icon
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path
fill="currentColor"
d="M17.891 12a5.94 5.94 0 0 1-3.68 5.499a5.97 5.97 0 0 1-6.496-1.295A5.948 5.948 0 0 1 11.943 6.05a5.96 5.96 0 0 1 4.21 1.743A5.94 5.94 0 0 1 17.89 12M3.203 13.048H2.05A1.05 1.05 0 0 1 1 12a1.047 1.047 0 0 1 1.05-1.048h1.153A1.05 1.05 0 0 1 4.253 12a1.047 1.047 0 0 1-1.05 1.048m18.747 0h-1.143A1.05 1.05 0 0 1 19.758 12a1.047 1.047 0 0 1 1.05-1.048h1.143A1.05 1.05 0 0 1 23 12a1.047 1.047 0 0 1-1.05 1.048m-9.965-8.8a1.05 1.05 0 0 1-1.05-1.048V2.048A1.047 1.047 0 0 1 11.986 1a1.05 1.05 0 0 1 1.049 1.048V3.2a1.047 1.047 0 0 1-1.05 1.048m0 18.752a1.05 1.05 0 0 1-1.05-1.047V20.8a1.047 1.047 0 0 1 1.05-1.048a1.05 1.05 0 0 1 1.049 1.048v1.152A1.047 1.047 0 0 1 11.984 23M5.753 6.825a1.05 1.05 0 0 1-.745-.314l-.819-.807a1.051 1.051 0 0 1 .745-1.796c.28 0 .548.111.745.308l.819.817a1.047 1.047 0 0 1 0 1.478a1.05 1.05 0 0 1-.745.314m13.271 13.221a1.05 1.05 0 0 1-.735-.304l-.818-.817a1.047 1.047 0 0 1 1.14-1.739q.196.096.34.262l.818.817a1.047 1.047 0 0 1 0 1.477a1.05 1.05 0 0 1-.745.304m-.808-13.221a1.05 1.05 0 0 1-1.034-1.254c.04-.204.142-.391.29-.538l.818-.817a1.05 1.05 0 0 1 1.48 1.488l-.82.807a1.05 1.05 0 0 1-.734.314M4.934 20.046a1.05 1.05 0 0 1-.745-.304a1.046 1.046 0 0 1 0-1.477l.819-.817a1.05 1.05 0 0 1 1.49 0a1.047 1.047 0 0 1 0 1.477l-.819.817a1.05 1.05 0 0 1-.745.304"
/>
</svg>
)}
</button>
);
};

export default DarkButton;
29 changes: 29 additions & 0 deletions src/client/components/DarkModeProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, { createContext, useEffect, useState } from "react";

interface DarkModeContextProps {
darkMode: boolean;
toggleDarkMode: () => void;
}

export const DarkModeContext = createContext<DarkModeContextProps>({
darkMode: false,
toggleDarkMode: () => {},
});

export const DarkModeProvider = ({ children }: { children: React.ReactNode }) => {
const [darkMode, setDarkMode] = useState(() => {
if (typeof window !== "undefined") {
return localStorage.getItem("darkMode") === "true";
}
return false;
});

useEffect(() => {
localStorage.setItem("darkMode", darkMode.toString());
document.documentElement.classList.toggle("dark", darkMode);
}, [darkMode]);

const toggleDarkMode = () => setDarkMode((prev) => !prev);

return <DarkModeContext.Provider value={{ darkMode, toggleDarkMode }}>{children}</DarkModeContext.Provider>;
};
15 changes: 11 additions & 4 deletions src/client/components/navigation/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import { SearchBar } from "@navigation/SearchBar";
import { UserButton } from "@navigation/UserButton";
import { useLocation } from "@tanstack/react-router";
import { Squash as Hamburger } from "hamburger-react";
import React, { useEffect, useRef, useState } from "react";
import React, { useContext, useEffect, useRef, useState } from "react";
import DarkButton from "../DarkButton";
import { DarkModeContext } from "../DarkModeProvider";

const SCREEN_BREAKPOINT = 1024;

Expand Down Expand Up @@ -52,6 +54,7 @@ const Header: React.FC = () => {
const { isAuthenticated, isLoading, logout } = useAuth();
const menuRef = useRef<HTMLDivElement>(null);
const hamburgerRef = useRef<HTMLButtonElement>(null);
const { darkMode, toggleDarkMode } = useContext(DarkModeContext);

useEffect(() => {
const handleOutsideClick = (event: MouseEvent) => {
Expand Down Expand Up @@ -85,13 +88,16 @@ const Header: React.FC = () => {
<header
className={cn(`sticky left-0 top-0 z-50 w-full font-redhat font-medium shadow-md`, {
"bg-black text-white": isHomePage,
"bg-white text-black": !isHomePage,
"bg-background text-foreground": !isHomePage,
})}
>
<nav className="relative flex h-16 w-full items-center justify-between px-4 py-3 md:px-8">
{/* Logo */}
<Logo />

{/* TODO: For testing purposes */}

<DarkButton darkMode={darkMode} toggleDarkMode={toggleDarkMode} />
{/* Desktop Nav */}
<div className="hidden w-full items-center justify-between md:flex">
<div className="ml-auto flex items-center gap-4">
Expand All @@ -104,8 +110,9 @@ const Header: React.FC = () => {
</div>

{/* Mobile Nav */}
<div className="ml-auto flex items-center gap-2 md:hidden">
<SearchBar />
<div className="flex items-center gap-4 md:hidden">
<SearchBar className="w-32 focus:w-64" />
{!isLoading && <UserButton isLoggedIn={isAuthenticated} onLogout={logout} isHomePage={isHomePage} />}
<button ref={hamburgerRef} className="focus:outline-none">
<Hamburger toggled={menuOpen} toggle={setMenuOpen} color={isHomePage ? "#fff" : "#000"} size={22} />
</button>
Expand Down
14 changes: 8 additions & 6 deletions src/client/routes/__root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as React from "react";
import { Toaster } from "react-hot-toast";
import { seo } from "src/client/utils/seo";
import { AuthProvider } from "../AuthContext";
import { DarkModeProvider } from "../components/DarkModeProvider";
import Footer from "../components/navigation/Footer";
import Header from "../components/navigation/Header";
import css from "../index.css?url";
Expand Down Expand Up @@ -43,19 +44,20 @@ export const Route = createRootRoute({
});

function RootComponent() {
const [dark, toggleDark] = React.useState(true);
return (
<AuthProvider>
<RootDocument dark={dark} toggleDark={toggleDark}>
<Outlet />
</RootDocument>
<DarkModeProvider>
<RootDocument>
<Outlet />
</RootDocument>
</DarkModeProvider>
</AuthProvider>
);
}

function RootDocument({ children, dark, toggleDark }: { children: React.ReactNode; dark: boolean; toggleDark: () => void }) {
function RootDocument({ children }: { children: React.ReactNode }) {
return (
<Html className={dark ? "dark" : ""}>
<Html>
<Head>
<Meta />
<link rel="preconnect" href="https://fonts.googleapis.com" />
Expand Down
6 changes: 3 additions & 3 deletions src/client/routes/sports.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ export const Route = createFileRoute("/sports")({
<Carousel purpose="Images" prog="Sports" />
<header className="mb-6 flex max-w-7xl items-center px-5">
<div className="mr-3 h-11 w-1.5 bg-saseGreen"></div>
<h2 className="text-4xl text-muted-foreground">Testimonials</h2>
<h2 className="text-4xl text-foreground">Testimonials</h2>
</header>
<Carousel purpose="Testimonials" prog="Sports" />
<header className="mb-12 flex max-w-7xl items-center px-5">
<div className="mr-3 h-11 w-1.5 bg-saseGreen"></div>
<h2 className="text-4xl text-muted-foreground">Goals & Outcomes</h2>
<h2 className="text-4xl text-foreground">Goals & Outcomes</h2>
</header>
<div className="mb-24 flex flex-col flex-nowrap items-center justify-center gap-10 md:flex-row lg:gap-36">
<GoalCard text="Meet new people with common interests." color="blue" />
Expand All @@ -58,7 +58,7 @@ export const Route = createFileRoute("/sports")({
</div>
<header className="flex max-w-7xl items-center px-5">
<div className="mr-3 h-11 w-1.5 bg-saseGreen"></div>
<h2 className="text-4xl text-muted-foreground">FAQs</h2>
<h2 className="text-4xl text-foreground">FAQs</h2>
</header>
<FAQ faqData={faqData} />
</div>
Expand Down

0 comments on commit fcab651

Please sign in to comment.