Files
KatelyaTV/src/components/ThemeToggle.tsx
T
katelya 4617b0199b feat: Enhance package manager detection script and improve type safety in components
- Updated `check-package-manager.js` to disable specific ESLint rules for better readability.
- Refactored `page.tsx` in the login module to remove unnecessary type assertions and improve state management.
- Modified `page.tsx` in the home module to enhance error handling, improve layout with grid system, and limit displayed items.
- Adjusted `PageLayout.tsx` to implement responsive layout changes for the play page.
- Improved `ThemeToggle.tsx` to ensure proper dependency tracking in useEffect.
- Enhanced `VideoCard.tsx` with better type definitions for favorites.
- Updated `db.client.ts` to rename legacy cache prefix for future migration.
- Added runtime configuration types in `types.ts` and extended global Window interface.
- Introduced a new Workbox service worker file for improved caching strategies.
2025-09-01 21:23:45 +08:00

67 lines
1.9 KiB
TypeScript

'use client';
import { Moon, Sun } from 'lucide-react';
import { useTheme } from 'next-themes';
import { useEffect, useState } from 'react';
export function ThemeToggle() {
const [mounted, setMounted] = useState(false);
const { setTheme, resolvedTheme } = useTheme();
const setThemeColor = (theme?: string) => {
const meta = document.querySelector('meta[name="theme-color"]');
if (!meta) {
const meta = document.createElement('meta');
meta.name = 'theme-color';
meta.content = theme === 'dark' ? '#0c111c' : '#f9fbfe';
document.head.appendChild(meta);
} else {
meta.setAttribute('content', theme === 'dark' ? '#0c111c' : '#f9fbfe');
}
};
useEffect(() => {
setMounted(true);
setThemeColor(resolvedTheme);
}, [resolvedTheme]);
if (!mounted) {
// 渲染一个占位符以避免布局偏移
return <div className='w-10 h-10' />;
}
const toggleTheme = () => {
// 检查浏览器是否支持 View Transitions API
const targetTheme = resolvedTheme === 'dark' ? 'light' : 'dark';
setThemeColor(targetTheme);
// 使用更好的类型定义
const documentWithTransition = document as Document & {
startViewTransition?: (callback: () => void) => void;
};
if (!documentWithTransition.startViewTransition) {
setTheme(targetTheme);
return;
}
documentWithTransition.startViewTransition(() => {
setTheme(targetTheme);
});
};
return (
<button
onClick={toggleTheme}
className='w-10 h-10 p-2 rounded-full flex items-center justify-center text-gray-600 hover:bg-gray-200/50 dark:text-gray-300 dark:hover:bg-gray-700/50 transition-colors'
aria-label='Toggle theme'
>
{resolvedTheme === 'dark' ? (
<Sun className='w-full h-full' />
) : (
<Moon className='w-full h-full' />
)}
</button>
);
}