mercury/src/components/ThemeSwitcher.astro
2025-05-03 20:51:35 +08:00

119 lines
No EOL
3.1 KiB
Text

---
---
<div class="theme-dropdown" id="theme-dropdown">
<button class="theme-switcher" id="theme-switcher">Theme</button>
<div class="menu-body" id="menu-body">
<div class="dropdown-item" data-theme="auto">System</div>
<div class="dropdown-item" data-theme="dark">Dark</div>
<div class="dropdown-item" data-theme="light">Light</div>
</div>
</div>
<style>
.theme-dropdown {
position: relative;
display: inline-block;
}
.menu-body {
display: none;
position: fixed;
right: 45px;
bottom: 70px;
background-color: var(--bg-color);
border: 1px solid var(--border-color);
min-width: 140px;
z-index: 20;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.dropdown-item {
padding: 0.5rem 1rem;
cursor: pointer;
transition: background-color 0.2s ease;
}
.dropdown-item:hover {
background-color: var(--border-color);
}
.dropdown-item.active {
color: var(--accent-color);
font-weight: bold;
}
.theme-dropdown:hover .menu-body {
display: block;
}
</style>
<script>
// Constants for theme options
const THEME_AUTO = 'auto';
const THEME_DARK = 'dark';
const THEME_LIGHT = 'light';
// DOM elements
const themeDropdown = document.getElementById('theme-dropdown');
const menuBody = document.getElementById('menu-body');
const dropdownItems = document.querySelectorAll('.dropdown-item');
const root = document.documentElement;
// Get system preference
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const systemTheme = prefersDark ? THEME_DARK : THEME_LIGHT;
// Get saved theme from localStorage or default to auto
const savedThemeMode = localStorage.getItem('themeMode') || THEME_AUTO;
const savedTheme = localStorage.getItem('theme');
// Function to update active state in dropdown menu
function updateActiveState(activeTheme) {
dropdownItems.forEach(item => {
if (item.getAttribute('data-theme') === activeTheme) {
item.classList.add('active');
} else {
item.classList.remove('active');
}
});
}
// Function to apply theme
function applyTheme(themeMode) {
// Update active state in dropdown
updateActiveState(themeMode);
// Save theme mode preference
localStorage.setItem('themeMode', themeMode);
// Apply the appropriate theme
if (themeMode === THEME_AUTO) {
// Follow system
localStorage.removeItem('theme');
root.removeAttribute('data-theme');
} else {
// Set to specific theme
root.setAttribute('data-theme', themeMode);
localStorage.setItem('theme', themeMode);
}
}
// Initialize theme
applyTheme(savedThemeMode);
// Add click handlers to dropdown items
dropdownItems.forEach(item => {
item.addEventListener('click', () => {
const selectedTheme = item.getAttribute('data-theme');
applyTheme(selectedTheme);
});
});
// Listen for system preference changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
if (savedThemeMode === THEME_AUTO) {
// Only update if we're in auto mode
root.removeAttribute('data-theme');
}
});
</script>