Merge pull request #129 from GrothKeiran/feat/add-switchable-pure-white-theme

feat(theme): add switchable pure-white theme
This commit is contained in:
Supra4E8C
2026-03-07 16:20:11 +08:00
committed by GitHub
Unverified
7 changed files with 91 additions and 8 deletions
+9 -1
View File
@@ -117,6 +117,12 @@ const headerIcons = {
<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9z" />
</svg>
),
whiteTheme: (
<svg {...headerIconProps}>
<circle cx="12" cy="12" r="7" />
<circle cx="12" cy="12" r="3" fill="currentColor" stroke="none" />
</svg>
),
autoTheme: (
<svg {...headerIconProps}>
<defs>
@@ -571,7 +577,9 @@ export function MainLayout() {
? headerIcons.autoTheme
: theme === 'dark'
? headerIcons.moon
: headerIcons.sun}
: theme === 'white'
? headerIcons.whiteTheme
: headerIcons.sun}
</Button>
<Button variant="ghost" size="sm" onClick={logout} title={t('header.logout')}>
{headerIcons.logout}
+1
View File
@@ -1400,6 +1400,7 @@
"theme": {
"switch": "Theme",
"light": "Light",
"white": "Pure White",
"dark": "Dark",
"switch_to_light": "Switch to light mode",
"switch_to_dark": "Switch to dark mode",
+1
View File
@@ -1405,6 +1405,7 @@
"theme": {
"switch": "Тема",
"light": "Светлая",
"white": "Чисто-белая",
"dark": "Тёмная",
"switch_to_light": "Переключиться на светлую тему",
"switch_to_dark": "Переключиться на тёмную тему",
+1
View File
@@ -1400,6 +1400,7 @@
"theme": {
"switch": "主题",
"light": "亮色",
"white": "纯白",
"dark": "暗色",
"switch_to_light": "切换到亮色模式",
"switch_to_dark": "切换到暗色模式",
+25 -6
View File
@@ -25,12 +25,28 @@ const getSystemTheme = (): ResolvedTheme => {
return 'light';
};
const applyTheme = (resolved: ResolvedTheme) => {
const resolveTheme = (theme: Theme): ResolvedTheme | 'white' => {
if (theme === 'auto') {
return getSystemTheme();
}
if (theme === 'white') {
return 'white';
}
return theme;
};
const applyTheme = (resolved: ResolvedTheme | 'white') => {
if (resolved === 'dark') {
document.documentElement.setAttribute('data-theme', 'dark');
} else {
document.documentElement.removeAttribute('data-theme');
return;
}
if (resolved === 'white') {
document.documentElement.setAttribute('data-theme', 'white');
return;
}
document.documentElement.removeAttribute('data-theme');
};
export const useThemeStore = create<ThemeState>()(
@@ -40,14 +56,17 @@ export const useThemeStore = create<ThemeState>()(
resolvedTheme: 'light',
setTheme: (theme) => {
const resolved: ResolvedTheme = theme === 'auto' ? getSystemTheme() : theme;
const resolved = resolveTheme(theme);
applyTheme(resolved);
set({ theme, resolvedTheme: resolved });
set({
theme,
resolvedTheme: resolved === 'white' ? 'light' : resolved,
});
},
cycleTheme: () => {
const { theme, setTheme } = get();
const order: Theme[] = ['light', 'dark', 'auto'];
const order: Theme[] = ['light', 'white', 'dark', 'auto'];
const currentIndex = order.indexOf(theme);
const nextTheme = order[(currentIndex + 1) % order.length];
setTheme(nextTheme);
+53
View File
@@ -56,6 +56,59 @@
--accent-tertiary: var(--bg-tertiary);
}
// 纯白主题
[data-theme='white'] {
--bg-secondary: #ffffff;
--bg-primary: #ffffff;
--bg-tertiary: #f6f6f6;
--bg-hover: var(--bg-tertiary);
--bg-quinary: #ffffff;
--bg-error-light: rgba(198, 87, 70, 0.08);
--text-primary: #2d2a26;
--text-secondary: #6d6760;
--text-tertiary: #a29c95;
--text-quaternary: #c0bab3;
--text-muted: var(--text-tertiary);
--border-color: #e5e5e5;
--border-secondary: var(--border-color);
--border-primary: #d9d9d9;
--border-hover: #cccccc;
--primary-color: #8b8680;
--primary-hover: #7f7a74;
--primary-active: #726d67;
--primary-contrast: #ffffff;
--success-color: #10b981;
--warning-color: #c65746;
--error-color: #c65746;
--danger-color: var(--error-color);
--info-color: var(--primary-color);
--warning-bg: rgba(198, 87, 70, 0.12);
--warning-border: rgba(198, 87, 70, 0.35);
--warning-text: var(--warning-color);
--success-badge-bg: #d1fae5;
--success-badge-text: #065f46;
--success-badge-border: #6ee7b7;
--failure-badge-bg: rgba(198, 87, 70, 0.14);
--failure-badge-text: #8a3a30;
--failure-badge-border: rgba(198, 87, 70, 0.35);
--count-badge-bg: rgba(139, 134, 128, 0.18);
--count-badge-text: var(--primary-active);
--shadow: 0 1px 2px 0 rgb(0 0 0 / 0.08);
--shadow-lg: 0 10px 18px -3px rgb(0 0 0 / 0.1);
--radius-md: 8px;
--accent-tertiary: var(--bg-tertiary);
}
// 深色主题(#191919
[data-theme='dark'] {
// 极简暖灰:深色模式(提升对比度与层级)
+1 -1
View File
@@ -2,7 +2,7 @@
* 通用类型定义
*/
export type Theme = 'light' | 'dark' | 'auto';
export type Theme = 'light' | 'white' | 'dark' | 'auto';
export type Language = 'zh-CN' | 'en' | 'ru';