Track Better includes a beautiful dark mode that adapts to your preferences. Switch between light and dark themes manually or let the app follow your system preferences.
The theme toggle button is located in the top-right corner of the app header, next to the install button.
Click the button to instantly switch between themes:
Light mode : Shows a moon icon
Dark mode : Shows a sun icon
How It Works
Track Better uses the useLocalStorage hook to persist your theme preference across sessions. The theme state is managed in the main App component.
Theme State Management
const [ theme , setTheme ] = useLocalStorage ( "theme" , "light" );
The theme is stored in localStorage with the key "theme" and defaults to "light" mode.
Toggle Implementation
< Button
type = "button"
size = "icon"
variant = "outline"
className = "rounded-full border-slate-300/80 bg-white/90 dark:border-zinc-700 dark:bg-zinc-900"
onClick = { () => setTheme (( prevTheme ) => ( prevTheme === "dark" ? "light" : "dark" )) }
aria-label = { isDark ? "Switch to light mode" : "Switch to dark mode" }
title = { isDark ? "Switch to light mode" : "Switch to dark mode" }
>
{ isDark ? < Sun className = "h-4 w-4 text-amber-300" /> : < Moon className = "h-4 w-4 text-slate-800" /> }
</ Button >
The button toggles between “dark” and “light” values, updating the state and triggering a re-render.
Theme Application
When the theme changes, a useEffect hook applies the theme to the document:
useEffect (() => {
const root = document . documentElement ;
root . classList . toggle ( "dark" , isDark );
const metaTheme = document . querySelector ( 'meta[name="theme-color"]' );
if ( metaTheme ) {
metaTheme . setAttribute ( "content" , isDark ? "#020617" : "#0f172a" );
}
// Update favicon based on theme
const faviconLink = document . getElementById ( "favicon" );
if ( faviconLink ) {
faviconLink . href = isDark ? "/icon-dark.svg" : "/icon-light.svg" ;
}
}, [ isDark ]);
This effect:
Adds/removes the dark class on the <html> element
Updates the theme-color meta tag for mobile browsers
Changes the favicon to match the current theme
The dark class is used by Tailwind CSS to apply dark mode styles throughout the app.
Automatic System Preference
While Track Better defaults to light mode, you can extend it to detect system preferences automatically:
const [ theme , setTheme ] = useLocalStorage (
"theme" ,
window . matchMedia ( "(prefers-color-scheme: dark)" ). matches ? "dark" : "light"
);
This checks the user’s system color scheme preference on first load.
Theme Persistence
The useLocalStorage hook automatically persists the theme preference:
useEffect (() => {
try {
window . localStorage . setItem ( key , JSON . stringify ( storedValue ));
} catch ( error ) {
console . error ( `Failed to save localStorage key " ${ key } "` , error );
}
}, [ key , storedValue ]);
Your theme preference is saved to localStorage and restored when you return to the app, even after closing the browser or clearing your cache (unless you clear localStorage).
Customizing Theme Colors
Track Better uses Tailwind CSS with a custom color palette optimized for both themes. The main colors are:
Background: white ( #ffffff )
Text : slate-900 ( #0f172a )
Accent: cyan-600 ( #0891b2 )
Border: slate-300 ( #cbd5e1 )
Accessibility
The theme toggle button includes proper accessibility attributes:
aria-label : Describes the action (“Switch to light mode” / “Switch to dark mode”)
title : Provides a tooltip on hover
Icon semantics : Moon icon for light mode (switch to dark), Sun icon for dark mode (switch to light)
The theme preference is device-specific. If you use Track Better on multiple devices, each device maintains its own theme setting.
Settings Customize other app preferences
PWA Installation Install Track Better as a standalone app