Skip to main content
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.

Theme Toggle Button

The theme toggle button is located in the top-right corner of the app header, next to the install button. Theme toggle 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

App.jsx:34
const [theme, setTheme] = useLocalStorage("theme", "light");
The theme is stored in localStorage with the key "theme" and defaults to "light" mode.

Toggle Implementation

App.jsx:243
<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:
App.jsx:69-83
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:
  1. Adds/removes the dark class on the <html> element
  2. Updates the theme-color meta tag for mobile browsers
  3. 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:
useLocalStorage.js:22-28
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

Build docs developers (and LLMs) love