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:
parent
87cbfe87ee
commit
c012425ceb
5 changed files with 32 additions and 7 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
import { Routes, Route, Navigate } from 'react-router-dom';
|
import { Routes, Route, Navigate } from 'react-router-dom';
|
||||||
import { Sidebar } from './components/Sidebar';
|
import { Sidebar } from './components/Sidebar';
|
||||||
import { ToastProvider } from './components/Toast';
|
import { ToastProvider } from './components/Toast';
|
||||||
|
import { useTheme } from './hooks/useTheme';
|
||||||
import { Channels } from './pages/Channels';
|
import { Channels } from './pages/Channels';
|
||||||
import { ChannelDetail } from './pages/ChannelDetail';
|
import { ChannelDetail } from './pages/ChannelDetail';
|
||||||
import { Library } from './pages/Library';
|
import { Library } from './pages/Library';
|
||||||
|
|
@ -10,6 +11,8 @@ import { SettingsPage } from './pages/Settings';
|
||||||
import { SystemPage } from './pages/System';
|
import { SystemPage } from './pages/System';
|
||||||
|
|
||||||
function AuthenticatedLayout() {
|
function AuthenticatedLayout() {
|
||||||
|
// Apply theme from settings to documentElement at the app root
|
||||||
|
useTheme();
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', minHeight: '100vh' }}>
|
<div style={{ display: 'flex', minHeight: '100vh' }}>
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
|
|
|
||||||
21
src/frontend/src/hooks/useTheme.ts
Normal file
21
src/frontend/src/hooks/useTheme.ts
Normal 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;
|
||||||
|
}
|
||||||
|
|
@ -1891,12 +1891,12 @@ export function ChannelDetail() {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 'var(--space-3)',
|
gap: 'var(--space-3)',
|
||||||
padding: 'var(--space-3) var(--space-5)',
|
padding: 'var(--space-3) var(--space-5)',
|
||||||
backgroundColor: 'rgba(30, 32, 40, 0.75)',
|
backgroundColor: 'var(--glass-bg)',
|
||||||
backdropFilter: 'blur(16px) saturate(1.4)',
|
backdropFilter: 'blur(16px) saturate(1.4)',
|
||||||
WebkitBackdropFilter: '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)',
|
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
|
<span
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,8 @@ export function SettingsPage() {
|
||||||
}
|
}
|
||||||
}, [appSettings]);
|
}, [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(() => {
|
useEffect(() => {
|
||||||
document.documentElement.dataset.theme = theme;
|
document.documentElement.dataset.theme = theme;
|
||||||
localStorage.setItem('tubearr-theme', theme);
|
localStorage.setItem('tubearr-theme', theme);
|
||||||
|
|
|
||||||
|
|
@ -60,12 +60,12 @@ a:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: rgba(255, 255, 255, 0.08);
|
background: var(--bg-selected);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
::-webkit-scrollbar-thumb:hover {
|
||||||
background: rgba(255, 255, 255, 0.15);
|
background: var(--border-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Buttons base ── */
|
/* ── Buttons base ── */
|
||||||
|
|
@ -158,7 +158,7 @@ tr:hover {
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
90deg,
|
90deg,
|
||||||
var(--bg-input) 25%,
|
var(--bg-input) 25%,
|
||||||
rgba(255, 255, 255, 0.04) 50%,
|
var(--bg-hover) 50%,
|
||||||
var(--bg-input) 75%
|
var(--bg-input) 75%
|
||||||
);
|
);
|
||||||
background-size: 200% 100%;
|
background-size: 200% 100%;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue