feat(theme): 专业主题系统重构 — Warp/Linear 设计参考,深色/浅色完整适配

参考设计系统:
- Warp: 温暖暗色调、自然层次、克制配色
- Linear: 亮度阶梯层次、半透明边框、精确排版

核心改进:
- app-theme.ts: 完整重写深色/浅色调色板 (+surface-hover/active, border-subtle/focus, feedback-bg, placeholder)
- useTheme.ts: 修复硬编码 return 'dark',支持 dark/light/system 完整切换
- index.css: 消除硬编码颜色,全部使用 CSS 变量
- tailwind.config.js: 新增 txt/content/surface/border/ph/feedback 语义 token
- 44 文件批量迁移: 292 处 text-gray/bg-gray/text-white/placeholder-gray → 主题感知语义 token

| 44 files +611/-482 | tsc零错误 | 96/96 tests passing
This commit is contained in:
OpsXShell Dev committed 2026-04-25 19:31:51 +08:00
1 parent 07c4a5b14f
commit e9a0d21758
44 files changed
+593 -464

No files matched your search

+21 -9
View File
@@ -6,9 +6,12 @@ import { darkColors, lightColors, type AppThemeMode, type ColorMap } from '../th
* Resolves the *effective* theme ('dark' | 'light') from the user preference,
* including the 'system' → prefers-color-scheme mapping.
*/
function resolveEffectiveTheme(_preference: AppThemeMode): 'dark' | 'light' {
// 当前版本固定使用 dark 主题,后续版本开放主题切换
return 'dark'
function resolveEffectiveTheme(preference: AppThemeMode): 'dark' | 'light' {
if (preference === 'system') {
if (typeof window === 'undefined') return 'dark'
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
return preference
}
/**
@@ -38,8 +41,10 @@ export function useTheme() {
useEffect(() => {
const colors = effective === 'dark' ? darkColors : lightColors
// Set data attribute for potential direct CSS selectors
// Set data attribute for CSS selectors
document.documentElement.setAttribute('data-theme', effective)
// Toggle Tailwind dark class
if (effective === 'dark') {
document.documentElement.classList.add('dark')
} else {
@@ -49,9 +54,9 @@ export function useTheme() {
// Apply CSS custom properties
applyCSSVars(colors)
// Update body bg & colour (mirrors index.css body rules but via vars)
document.body.style.backgroundColor = '#0f172a'
document.body.style.color = '#e2e8f0'
// Update body bg & colour from tokens (not hardcoded)
document.body.style.backgroundColor = colors['surface-base'] || '#0f172a'
document.body.style.color = colors['text-primary'] || '#e2e8f0'
}, [effective])
// Listen for system colour-scheme changes when preference is 'system'
@@ -64,9 +69,16 @@ export function useTheme() {
const newEffective = e.matches ? 'dark' : 'light'
const colors = e.matches ? darkColors : lightColors
document.documentElement.setAttribute('data-theme', newEffective)
if (newEffective === 'dark') {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
applyCSSVars(colors)
document.body.style.backgroundColor = '#0f172a'
document.body.style.color = '#e2e8f0'
document.body.style.backgroundColor = colors['surface-base'] || '#0f172a'
document.body.style.color = colors['text-primary'] || '#e2e8f0'
}
mql.addEventListener('change', handler)