refactor: 移除主题切换功能,统一使用明亮风格
- 从 Header 移除 ThemeToggle 组件 - 删除 theme-toggle.tsx 文件 - 简化 theme-context.tsx,只保留 light 主题~
This commit is contained in:
@@ -4,7 +4,6 @@ import { useState, useEffect, useCallback } from 'react';
|
||||
import { Menu, X } from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ThemeToggle } from '@/components/ui/theme-toggle';
|
||||
import { COMPANY_INFO, NAVIGATION } from '@/lib/constants';
|
||||
|
||||
export function Header() {
|
||||
@@ -64,7 +63,7 @@ export function Header() {
|
||||
fixed top-0 left-0 right-0 z-50
|
||||
transition-all duration-300 ease-out
|
||||
${isScrolled
|
||||
? 'bg-[var(--color-bg-primary)]/80 backdrop-blur-xl border-b border-[var(--color-border-primary)] shadow-[0_4px_30px_rgba(0,217,255,0.1)]'
|
||||
? 'bg-white/95 backdrop-blur-xl border-b border-[#E2E8F0] shadow-sm'
|
||||
: 'bg-transparent'
|
||||
}
|
||||
`}
|
||||
@@ -93,8 +92,8 @@ export function Header() {
|
||||
relative px-3 py-1.5 text-sm font-medium
|
||||
transition-all duration-300
|
||||
${activeSection === item.id.replace('#', '')
|
||||
? 'text-[var(--color-tech-blue)]'
|
||||
: 'text-[var(--color-text-secondary)] hover:text-[var(--color-tech-blue)]'
|
||||
? 'text-[#005EB8]'
|
||||
: 'text-[#4A5568] hover:text-[#005EB8]'
|
||||
}
|
||||
`}
|
||||
>
|
||||
@@ -102,7 +101,7 @@ export function Header() {
|
||||
{activeSection === item.id.replace('#', '') && (
|
||||
<motion.span
|
||||
layoutId="activeNav"
|
||||
className="absolute bottom-0 left-1/2 -translate-x-1/2 w-6 h-0.5 bg-gradient-to-r from-[var(--color-tech-blue)] to-[var(--color-tech-purple)] rounded-full"
|
||||
className="absolute bottom-0 left-1/2 -translate-x-1/2 w-6 h-0.5 bg-[#005EB8] rounded-full"
|
||||
transition={{ type: "spring", stiffness: 380, damping: 30 }}
|
||||
/>
|
||||
)}
|
||||
@@ -111,7 +110,6 @@ export function Header() {
|
||||
</nav>
|
||||
|
||||
<div className="hidden md:flex items-center gap-3">
|
||||
<ThemeToggle />
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@@ -138,7 +136,7 @@ export function Header() {
|
||||
</div>
|
||||
|
||||
<button
|
||||
className="md:hidden p-2 -mr-2 text-[var(--color-text-secondary)] hover:text-[var(--color-tech-blue)] transition-colors"
|
||||
className="md:hidden p-2 -mr-2 text-[#4A5568] hover:text-[#005EB8] transition-colors"
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
>
|
||||
{isOpen ? <X className="w-5 h-5" /> : <Menu className="w-5 h-5" />}
|
||||
@@ -156,7 +154,7 @@ export function Header() {
|
||||
className="fixed inset-0 z-40 md:hidden"
|
||||
>
|
||||
<div
|
||||
className="absolute inset-0 bg-black/60 backdrop-blur-sm"
|
||||
className="absolute inset-0 bg-black/20 backdrop-blur-sm"
|
||||
onClick={() => setIsOpen(false)}
|
||||
/>
|
||||
<motion.div
|
||||
@@ -164,7 +162,7 @@ export function Header() {
|
||||
animate={{ y: 0, opacity: 1 }}
|
||||
exit={{ y: -20, opacity: 0 }}
|
||||
transition={{ type: "spring", stiffness: 300, damping: 30 }}
|
||||
className="absolute top-16 left-0 right-0 bg-[var(--color-bg-secondary)]/95 backdrop-blur-xl border-b border-[var(--color-border-primary)] shadow-[0_4px_30px_rgba(0,217,255,0.1)]"
|
||||
className="absolute top-16 left-0 right-0 bg-white/95 backdrop-blur-xl border-b border-[#E2E8F0] shadow-lg"
|
||||
>
|
||||
<nav className="container-wide py-4">
|
||||
{NAVIGATION.map((item, index) => (
|
||||
@@ -180,19 +178,15 @@ export function Header() {
|
||||
transition-all duration-300
|
||||
border-l-2
|
||||
${activeSection === item.id.replace('#', '')
|
||||
? 'text-[var(--color-tech-blue)] border-[var(--color-tech-blue)] bg-[rgba(0,217,255,0.1)]'
|
||||
: 'text-[var(--color-text-secondary)] border-transparent hover:text-[var(--color-tech-blue)] hover:bg-[rgba(255,255,255,0.05)]'
|
||||
? 'text-[#005EB8] border-[#005EB8] bg-[#E8F4FD]'
|
||||
: 'text-[#4A5568] border-transparent hover:text-[#005EB8] hover:bg-[#F5F7FA]'
|
||||
}
|
||||
`}
|
||||
>
|
||||
{item.label}
|
||||
</motion.a>
|
||||
))}
|
||||
<div className="mt-4 px-4 pt-4 border-t border-[var(--color-border-primary)] space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-[var(--color-text-tertiary)]">主题模式</span>
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
<div className="mt-4 px-4 pt-4 border-t border-[#E2E8F0] space-y-3">
|
||||
<Button
|
||||
className="w-full"
|
||||
onClick={() => {
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { useTheme } from '@/contexts/theme-context';
|
||||
import { Moon, Sun, Monitor } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
|
||||
export function ThemeToggle() {
|
||||
const { theme, setTheme, resolvedTheme } = useTheme();
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="sm" className="relative w-9 h-9 p-0">
|
||||
<Sun className="h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon className="absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
<span className="sr-only">切换主题</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem onClick={() => setTheme('light')}>
|
||||
<Sun className="mr-2 h-4 w-4" />
|
||||
<span>浅色</span>
|
||||
{theme === 'light' && <span className="ml-auto text-[#C41E3A]">✓</span>}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setTheme('dark')}>
|
||||
<Moon className="mr-2 h-4 w-4" />
|
||||
<span>深色</span>
|
||||
{theme === 'dark' && <span className="ml-auto text-[#C41E3A]">✓</span>}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setTheme('system')}>
|
||||
<Monitor className="mr-2 h-4 w-4" />
|
||||
<span>跟随系统</span>
|
||||
{theme === 'system' && <span className="ml-auto text-[#C41E3A]">✓</span>}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
@@ -1,65 +1,17 @@
|
||||
'use client';
|
||||
|
||||
import { createContext, useContext, useEffect, useState, type ReactNode } from 'react';
|
||||
|
||||
type Theme = 'light' | 'dark' | 'system';
|
||||
import { createContext, useContext, type ReactNode } from 'react';
|
||||
|
||||
interface ThemeContextType {
|
||||
theme: Theme;
|
||||
setTheme: (theme: Theme) => void;
|
||||
resolvedTheme: 'light' | 'dark';
|
||||
theme: 'light';
|
||||
resolvedTheme: 'light';
|
||||
}
|
||||
|
||||
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
|
||||
|
||||
const THEME_STORAGE_KEY = 'ruixin-theme';
|
||||
|
||||
export function ThemeProvider({ children }: { children: ReactNode }) {
|
||||
const [theme, setThemeState] = useState<Theme>('system');
|
||||
const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>('light');
|
||||
|
||||
useEffect(() => {
|
||||
const stored = localStorage.getItem(THEME_STORAGE_KEY) as Theme | null;
|
||||
if (stored && ['light', 'dark', 'system'].includes(stored)) {
|
||||
setThemeState(stored);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const root = document.documentElement;
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
|
||||
const updateTheme = () => {
|
||||
let resolved: 'light' | 'dark';
|
||||
|
||||
if (theme === 'system') {
|
||||
resolved = mediaQuery.matches ? 'dark' : 'light';
|
||||
} else {
|
||||
resolved = theme;
|
||||
}
|
||||
|
||||
setResolvedTheme(resolved);
|
||||
|
||||
if (resolved === 'dark') {
|
||||
root.classList.add('dark');
|
||||
} else {
|
||||
root.classList.remove('dark');
|
||||
}
|
||||
};
|
||||
|
||||
updateTheme();
|
||||
|
||||
mediaQuery.addEventListener('change', updateTheme);
|
||||
return () => mediaQuery.removeEventListener('change', updateTheme);
|
||||
}, [theme]);
|
||||
|
||||
const setTheme = (newTheme: Theme) => {
|
||||
setThemeState(newTheme);
|
||||
localStorage.setItem(THEME_STORAGE_KEY, newTheme);
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={{ theme, setTheme, resolvedTheme }}>
|
||||
<ThemeContext.Provider value={{ theme: 'light', resolvedTheme: 'light' }}>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user