Theme Toggle Component
The theme toggle is implemented insrc/components/ThemeToggle.astro with support for both desktop and mobile versions.
Component Structure
- Uses Lucide icons for Moon/Sun
- Supports separate desktop and mobile instances
- Tracks analytics with Umami
- Proper ARIA labels for accessibility
Theme Management Logic
The theme system uses inline scripts to prevent flash of unstyled content (FOUC).Core Functions
getTheme()
Retrieves the saved theme preference or defaults to dark:restoreTheme()
Applies the saved theme on page load:data-theme attribute on the <html> element:
updateIcons()
Toggles icon visibility based on current theme:- Dark mode: Shows Moon icon
- Light mode: Shows Sun icon
- Updates both desktop and mobile versions
toggleTheme()
Switches between themes and persists the choice:- Check current theme
- Calculate opposite theme
- Update DOM attribute
- Save to localStorage
- Update icon visibility
Event Listener Setup
The component prevents duplicate listeners using a customhasListener flag:
Initialization
The theme system initializes on page load and after navigation:DOMContentLoadedlistener: Handles initial page load- Direct
initialize()call: Runs if script loads after DOM is ready astro:page-load: Re-initializes after Astro View Transitions
CSS Variables Implementation
The theme system likely uses CSS custom properties for colors. While not shown in the component file, the typical pattern would be:LocalStorage Structure
The theme preference is stored as a simple key-value pair:- Key:
theme - Value:
"dark"or"light" - Persists across sessions
- Domain-specific
Preventing Flash of Unstyled Content (FOUC)
The component usesis:inline to execute immediately:
is:inline?
- Script runs immediately, not deferred
- Prevents bundling/minification
- Executes before page renders
- Eliminates theme flash on page load
View Transitions Compatibility
Astro’s View Transitions require special handling:- Add duplicate click listeners
- Cause multiple theme toggles per click
- Break icon synchronization
Analytics Integration
Theme toggles are tracked with custom events:- How often users change themes
- Desktop vs mobile usage
- Theme preferences over time
Accessibility Features
ARIA labels
ARIA labels
Semantic HTML
Semantic HTML
Uses proper
<button> elements with type="button" to prevent form submission.Keyboard navigation
Keyboard navigation
Visual feedback
Visual feedback
Icons change based on current state, providing visual confirmation of the active theme.
Usage in Layout
Include the component in your layout:Default Theme
The system defaults to dark mode:src/layouts/Base.astro:30
Best Practices
Use inline scripts for theme restoration
Use inline scripts for theme restoration
Always restore themes with inline scripts to prevent FOUC:
Handle View Transitions carefully
Handle View Transitions carefully
Re-initialize theme logic after navigation:
Prevent duplicate event listeners
Prevent duplicate event listeners
Track listener state to avoid duplicates:
Synchronize multiple toggle instances
Synchronize multiple toggle instances
Ensure desktop and mobile toggles stay in sync by:
- Using the same localStorage key
- Updating all icons in
updateIcons() - Sharing the same
data-themeattribute