fix: Created useTheme hook for App-level theme application, fixed hardc…

- "src/frontend/src/hooks/useTheme.ts"
- "src/frontend/src/App.tsx"
- "src/frontend/src/styles/global.css"
- "src/frontend/src/pages/ChannelDetail.tsx"

GSD-Task: S08/T03
This commit is contained in:
jlightner 2026-04-04 07:31:23 +00:00
parent 87cbfe87ee
commit c012425ceb
5 changed files with 32 additions and 7 deletions

View file

@ -1,6 +1,7 @@
import { Routes, Route, Navigate } from 'react-router-dom';
import { Sidebar } from './components/Sidebar';
import { ToastProvider } from './components/Toast';
import { useTheme } from './hooks/useTheme';
import { Channels } from './pages/Channels';
import { ChannelDetail } from './pages/ChannelDetail';
import { Library } from './pages/Library';
@ -10,6 +11,8 @@ import { SettingsPage } from './pages/Settings';
import { SystemPage } from './pages/System';
function AuthenticatedLayout() {
// Apply theme from settings to documentElement at the app root
useTheme();
return (
<div style={{ display: 'flex', minHeight: '100vh' }}>
<Sidebar />

View file

@ -0,0 +1,21 @@
import { useEffect } from 'react';
import { useAppSettings } from '../api/hooks/useSystem';
/**
* Reads the user-configured theme from app settings and applies it
* to the document element. Falls back to localStorage (set by the
* inline script in index.html) then 'dark'.
*
* Call once near the app root so theme stays in sync across all pages.
*/
export function useTheme(): 'dark' | 'light' {
const { data: settings } = useAppSettings();
const theme: 'dark' | 'light' = settings?.theme ?? (localStorage.getItem('tubearr-theme') as 'dark' | 'light') ?? 'dark';
useEffect(() => {
document.documentElement.dataset.theme = theme;
localStorage.setItem('tubearr-theme', theme);
}, [theme]);
return theme;
}

View file

@ -1891,12 +1891,12 @@ export function ChannelDetail() {
alignItems: 'center',
gap: 'var(--space-3)',
padding: 'var(--space-3) var(--space-5)',
backgroundColor: 'rgba(30, 32, 40, 0.75)',
backgroundColor: 'var(--glass-bg)',
backdropFilter: 'blur(16px) saturate(1.4)',
WebkitBackdropFilter: 'blur(16px) saturate(1.4)',
border: '1px solid rgba(255, 255, 255, 0.08)',
border: '1px solid var(--glass-border)',
borderRadius: 'var(--radius-xl)',
boxShadow: '0 8px 32px rgba(0, 0, 0, 0.35), inset 0 0.5px 0 rgba(255, 255, 255, 0.06)',
boxShadow: 'var(--shadow-md)',
}}
>
<span

View file

@ -140,7 +140,8 @@ export function SettingsPage() {
}
}, [appSettings]);
// Apply theme to document element + localStorage for instant apply on load
// Apply theme preview immediately when user toggles (before save).
// The App-level useTheme hook reconciles with the API value after save.
useEffect(() => {
document.documentElement.dataset.theme = theme;
localStorage.setItem('tubearr-theme', theme);

View file

@ -60,12 +60,12 @@ a:hover {
}
::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.08);
background: var(--bg-selected);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.15);
background: var(--border-light);
}
/* ── Buttons base ── */
@ -158,7 +158,7 @@ tr:hover {
background: linear-gradient(
90deg,
var(--bg-input) 25%,
rgba(255, 255, 255, 0.04) 50%,
var(--bg-hover) 50%,
var(--bg-input) 75%
);
background-size: 200% 100%;