3. Dark Mode

Dark Mode Documentation

This document explains the dark mode implementation in the project.

Overview

The application implements a comprehensive dark mode system that includes:

  • Light/Dark theme switching
  • System preference detection
  • Theme persistence
  • Smooth transitions
  • Consistent styling across components

Tailwind CSS Integration

The project uses Tailwind CSS for styling with dark mode support.

Tailwind Configuration

The dark mode is configured in tailwind.config.js:

module.exports = {
  darkMode: 'class',
  // ... other config
}

Implementation

Theme Context

The theme system is implemented using React Context:

type Theme = 'dark' | 'light' | 'system';

const ThemeProviderContext = createContext<ThemeProviderState>({
  theme: 'system',
  setTheme: () => null
});

Theme Provider

The ThemeProvider component manages theme state and persistence:

export function ThemeProvider({
  children,
  defaultTheme = 'system',
  storageKey = 'vite-ui-theme',
  ...props
}: ThemeProviderProps) {
  const [theme, setTheme] = useState<Theme>(
    () => (localStorage.getItem(storageKey) as Theme) || defaultTheme
  );

  useEffect(() => {
    const root = window.document.documentElement;
    root.classList.remove('light', 'dark');

    if (theme === 'system') {
      const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
        ? 'dark'
        : 'light';
      root.classList.add(systemTheme);
      return;
    }

    root.classList.add(theme);
  }, [theme]);
}

Custom Variants and Dark Mode Selectors

Custom Variant Syntax

The project uses a custom variant syntax for dark mode styling:

@custom-variant dark (&:is(.dark *));

Usage

Setting Up Theme Provider

Wrap your application with the ThemeProvider:

import { ThemeProvider } from '@/context/ThemeContext';

function App() {
  return (
    <ThemeProvider defaultTheme="system" storageKey="vite-ui-theme">
      {/* Your app components */}
    </ThemeProvider>
  );
}

Using Theme in Components

Access and modify theme in any component:

import { useTheme } from '@/context/ThemeContext';

function YourComponent() {
  const { theme, setTheme } = useTheme();

  return (
    <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
      Toggle Theme
    </button>
  );
}

Theme Features

1. Theme Options

  • light: Light theme
  • dark: Dark theme
  • system: Follows system preference

2. Persistence

  • Theme preference is saved to localStorage
  • Persists across page reloads
  • Customizable storage key

3. System Preference

  • Automatically detects system theme preference
  • Updates when system preference changes
  • Smooth transition between themes

4. CSS Integration

  • Uses CSS classes for theme application
  • Supports Tailwind dark mode
  • Easy to extend with custom styles

Theme Customization

Adding Custom Themes

  1. Extend the Theme type
  2. Update ThemeProvider logic
  3. Add corresponding CSS classes
  4. Implement theme switching UI

Modifying Colors

  1. Update CSS variables
  2. Modify Tailwind config
  3. Test contrast ratios
  4. Document changes