feat(ui): 实现深色/浅色主题切换功能

- 添加 CSS 变量定义浅色和深色主题色板
- 扩展 Tailwind 配置支持语义化颜色 (surface-*, fg-*, line-*, code)
- 创建 useTheme hook 管理主题状态和持久化
- 创建 ThemeToggle 组件支持三种模式 (light/dark/system)
- 迁移所有组件从硬编码 gray-* 到语义化颜色
- 支持系统主题偏好检测 (prefers-color-scheme)
- 添加主题初始化脚本防止闪烁 (FOUC)
This commit is contained in:
2025-12-15 15:47:32 +08:00
parent cd0dd814ab
commit 5b7b0ff1e4
39 changed files with 1002 additions and 652 deletions
+60 -14
View File
@@ -5,7 +5,54 @@
* 注意:使用此文件时,宿主项目需要配置 Tailwind CSS
*/
/* iOS Safe Area Support */
/* ============ 主题 CSS 变量 ============ */
:root {
/* 浅色主题 (默认) */
--color-bg-base: 255 255 255; /* #ffffff */
--color-bg-subtle: 246 248 250; /* #f6f8fa */
--color-bg-muted: 240 242 245; /* #f0f2f5 */
--color-bg-emphasis: 229 231 235; /* #e5e7eb */
--color-text-primary: 31 41 55; /* #1f2937 */
--color-text-secondary: 75 85 99; /* #4b5563 */
--color-text-muted: 107 114 128; /* #6b7280 */
--color-text-subtle: 156 163 175; /* #9ca3af */
--color-border-default: 229 231 235; /* #e5e7eb */
--color-border-muted: 209 213 219; /* #d1d5db */
--color-code-bg: 246 248 250; /* #f6f8fa */
/* 滚动条颜色 */
--scrollbar-thumb: #9ca3af;
--scrollbar-thumb-hover: #6b7280;
}
.dark {
/* 深色主题 */
--color-bg-base: 17 24 39; /* #111827 */
--color-bg-subtle: 31 41 55; /* #1f2937 */
--color-bg-muted: 55 65 81; /* #374151 */
--color-bg-emphasis: 75 85 99; /* #4b5563 */
--color-text-primary: 243 244 246; /* #f3f4f6 */
--color-text-secondary: 229 231 235; /* #e5e7eb */
--color-text-muted: 156 163 175; /* #9ca3af */
--color-text-subtle: 107 114 128; /* #6b7280 */
--color-border-default: 55 65 81; /* #374151 */
--color-border-muted: 75 85 99; /* #4b5563 */
--color-code-bg: 13 17 23; /* #0d1117 */
/* 滚动条颜色 */
--scrollbar-thumb: #4b5563;
--scrollbar-thumb-hover: #6b7280;
}
/* ============ iOS Safe Area Support ============ */
@supports (padding-bottom: env(safe-area-inset-bottom)) {
.safe-area-pb {
padding-bottom: calc(env(safe-area-inset-bottom) + 0.5rem);
@@ -26,7 +73,8 @@ html {
touch-action: pan-y;
}
/* Custom scrollbar */
/* ============ Custom scrollbar ============ */
::-webkit-scrollbar {
width: 8px;
height: 8px;
@@ -37,29 +85,30 @@ html {
}
::-webkit-scrollbar-thumb {
background: #4b5563;
background: var(--scrollbar-thumb);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
background: var(--scrollbar-thumb-hover);
}
/* Message content */
/* ============ Message content ============ */
.message-content {
max-width: none;
color: #f3f4f6; /* text-gray-100 */
color: rgb(var(--color-text-primary));
}
.message-content pre {
background: #1f2937; /* bg-gray-800 */
background: rgb(var(--color-code-bg));
border-radius: 0.5rem;
padding: 1rem;
overflow-x: auto;
}
.message-content code {
background: #1f2937; /* bg-gray-800 */
background: rgb(var(--color-code-bg));
padding: 0.125rem 0.375rem;
border-radius: 0.25rem;
font-size: 0.875rem;
@@ -70,7 +119,8 @@ html {
padding: 0;
}
/* Typing indicator */
/* ============ Typing indicator ============ */
.typing-indicator {
display: flex;
gap: 4px;
@@ -79,7 +129,7 @@ html {
.typing-indicator span {
width: 8px;
height: 8px;
background: #6b7280;
background: rgb(var(--color-text-muted));
border-radius: 50%;
animation: typing 1.4s infinite ease-in-out;
}
@@ -109,7 +159,3 @@ html {
}
}
/* bg-gray-850 custom color */
.bg-gray-850 {
background-color: #1a1f2a;
}