Files
nexus/wiki/concepts/Theme-Toggle.md
2026-05-03 05:42:12 +08:00

125 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Theme Toggle"
type: concept
tags: [css, javascript, ux, theme, dark-mode]
sources: [design-ux-architect.md]
last_updated: 2026-04-24
---
## Definition
Theme Toggle 是允许用户在 light、dark 和 system 三种主题模式之间切换的 UI 组件。所有新站点必须将此组件作为默认必备功能,基于 localStorage 持久化和 `prefers-color-scheme` 检测实现。
## HTML Structure
```html
<div class="theme-toggle" role="radiogroup" aria-label="Theme selection">
<button class="theme-toggle-option" data-theme="light" role="radio" aria-checked="false">
<span aria-hidden="true">☀️</span> Light
</button>
<button class="theme-toggle-option" data-theme="dark" role="radio" aria-checked="false">
<span aria-hidden="true">🌙</span> Dark
</button>
<button class="theme-toggle-option" data-theme="system" role="radio" aria-checked="true">
<span aria-hidden="true">💻</span> System
</button>
</div>
```
## CSS Styles
```css
.theme-toggle {
position: relative;
display: inline-flex;
align-items: center;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 24px;
padding: 4px;
transition: all 0.3s ease;
}
.theme-toggle-option {
padding: 8px 12px;
border-radius: 20px;
font-size: 14px;
font-weight: 500;
color: var(--text-secondary);
background: transparent;
border: none;
cursor: pointer;
transition: all 0.2s ease;
}
.theme-toggle-option.active {
background: var(--primary-500);
color: white;
}
```
## JavaScript Implementation
```javascript
class ThemeManager {
constructor() {
this.currentTheme = this.getStoredTheme() || this.getSystemTheme();
this.applyTheme(this.currentTheme);
this.initializeToggle();
}
getSystemTheme() {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
getStoredTheme() {
return localStorage.getItem('theme');
}
applyTheme(theme) {
if (theme === 'system') {
document.documentElement.removeAttribute('data-theme');
localStorage.removeItem('theme');
} else {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
}
this.currentTheme = theme;
this.updateToggleUI();
}
initializeToggle() {
const toggle = document.querySelector('.theme-toggle');
if (toggle) {
toggle.addEventListener('click', (e) => {
if (e.target.matches('.theme-toggle-option')) {
this.applyTheme(e.target.dataset.theme);
}
});
}
}
updateToggleUI() {
const options = document.querySelectorAll('.theme-toggle-option');
options.forEach(option => {
option.classList.toggle('active', option.dataset.theme === this.currentTheme);
});
}
}
document.addEventListener('DOMContentLoaded', () => {
new ThemeManager();
});
```
## Related Concepts
- [[CSS-Design-System]]:提供颜色变量系统支撑主题切换
- [[Theme-Manager]]JavaScript 主题状态管理类
- [[Responsive-Breakpoints]]:与其他响应式设计组件协同
- [[Layout-Framework]]:通常放置于 Header/Navigation 区域
## Sources
- [[design-ux-architect]] — Theme Toggle 的完整 HTML/CSS/JS 实现规范