feat(frontend): add dark mode option (#34)
All checks were successful
CI / Maven unit tests (push) Successful in 13s
CI / Build and push images (push) Successful in 48s
CI / Deploy to server (push) Successful in 19s

Resolves #32

Reviewed-on: #34
This commit was merged in pull request #34.
This commit is contained in:
2026-08-30 17:48:59 +01:00
parent ec9a982fe9
commit 7f58bad245
10 changed files with 239 additions and 30 deletions

View File

@@ -1,4 +1,4 @@
import { Menu, X } from 'lucide-react';
import { Menu, X, Sun, Moon } from 'lucide-react';
import { Dropdown, DropdownItem } from "./Dropdown.tsx";
import { GoogleLogin } from '@react-oauth/google';
@@ -8,6 +8,7 @@ import MenuButton from "./buttons/MenuButton.tsx";
import clsx from "clsx";
import {useNavigate} from "react-router-dom";
import { useAuth } from "../auth/useAuth.ts";
import { useTheme } from "../theme/useTheme.ts";
type props = {
@@ -25,6 +26,7 @@ const Topbar = ({
const navigate = useNavigate();
const { user, login, logout } = useAuth();
const { theme, toggleTheme } = useTheme();
const handleLogin = (response: CredentialResponse) => {
if (!response.credential) {
@@ -38,6 +40,8 @@ const Topbar = ({
});
}
const themeLabel = theme === "dark" ? "Switch to light mode" : "Switch to dark mode";
const handleLogout = () => {
logout()
.then(() => navigate("/"))
@@ -52,7 +56,16 @@ const Topbar = ({
{sidebarToggled ? <Menu size={24}/> : <X size={24}/>}
</MenuButton>
{ user ? (
<div className="flex items-center gap-1">
<MenuButton
onClick={toggleTheme}
title={themeLabel}
aria-label={themeLabel}
>
{theme === "dark" ? <Sun size={20}/> : <Moon size={20}/>}
</MenuButton>
{ user ? (
<div className={"hover:bg-hover rounded-lg p-0.5"}>
<img
className={"w-8 h-8 rounded-full inline-block"}
@@ -78,13 +91,15 @@ const Topbar = ({
className={"text-error font-medium"} />
</Dropdown>
</div>
) :
(
) :
(
<GoogleLogin
shape={"pill"}
theme={theme === "dark" ? "filled_black" : "outline"}
useOneTap={false}
onSuccess={(credentialResponse) => handleLogin(credentialResponse)} />
)}
)}
</div>
</div>
)
}

View File

@@ -65,7 +65,7 @@ const VideoCard = ({ id, title, duration, createdAt, onEdit, onDelete, className
className="w-full aspect-video object-cover group-hover:scale-105 transition-transform duration-200"
/>
<span className="absolute top-1.5 left-1.5 bg-text-primary/75 text-on-dark px-1.5 py-0.5 rounded text-xs font-data pointer-events-none">
<span className="absolute top-1.5 left-1.5 bg-media-backdrop/75 text-on-dark px-1.5 py-0.5 rounded text-xs font-data pointer-events-none">
{formatTime(duration)}
</span>
@@ -77,7 +77,7 @@ const VideoCard = ({ id, title, duration, createdAt, onEdit, onDelete, className
>
<button
onClick={(e) => stopAndRun(e, () => { setMenuOpen(v => !v); setConfirmDelete(false); })}
className="bg-text-primary/75 hover:bg-text-primary/90 text-on-dark rounded p-0.5 transition-colors"
className="bg-media-backdrop/75 hover:bg-media-backdrop/90 text-on-dark rounded p-0.5 transition-colors"
>
<MoreVertical size={14} />
</button>