theme-provider.tsx

Overview

The theme-provider.tsx file implements a React context-based theming solution designed to manage and persist the UI theme state across a React application. It provides a ThemeProvider component that wraps application parts to supply theme-related state and functionality, including the current theme and a method to update it. The theming system supports persistent storage using localStorage, automatically applies the theme CSS class to the root document element, and offers several React hooks to consume and manipulate theme state easily.

This file is central to managing light/dark mode toggling in the UI, leveraging React's Context API and hooks for clean, reusable, and encapsulated theme logic.


Detailed Documentation

Types

ThemeProviderProps

type ThemeProviderProps = {
  children: React.ReactNode;
  defaultTheme?: ThemeEnum;
  storageKey?: string;
};

ThemeProviderState

type ThemeProviderState = {
  theme: ThemeEnum;
  setTheme: (theme: ThemeEnum) => void;
};

Constants

initialState

const initialState: ThemeProviderState = {
  theme: ThemeEnum.Light,
  setTheme: () => null,
};

Context

ThemeProviderContext

const ThemeProviderContext = createContext<ThemeProviderState>(initialState);

Component: ThemeProvider

function ThemeProvider({
  children,
  defaultTheme = ThemeEnum.Light,
  storageKey = 'vite-ui-theme',
  ...props
}: ThemeProviderProps)

Internal behavior:

Returns:

Usage example:

import { ThemeProvider } from './theme-provider';
import { ThemeEnum } from '@/constants/common';

function App() {
  return (
    <ThemeProvider defaultTheme={ThemeEnum.Dark}>
      <MyAppComponents />
    </ThemeProvider>
  );
}

Hook: useTheme

export const useTheme = () => {
  const context = useContext(ThemeProviderContext);

  if (context === undefined)
    throw new Error('useTheme must be used within a ThemeProvider');

  return context;
};

Hook: useIsDarkTheme

export const useIsDarkTheme = () => {
  const { theme } = useTheme();
  return theme === ThemeEnum.Dark;
};
const isDark = useIsDarkTheme();
if (isDark) {
  // Apply dark theme-specific logic
}

Hook: useSwitchToDarkThemeOnMount

export function useSwitchToDarkThemeOnMount() {
  const { setTheme } = useTheme();

  useEffect(() => {
    setTheme(ThemeEnum.Dark);
  }, [setTheme]);
}
function ComponentThatForcesDarkTheme() {
  useSwitchToDarkThemeOnMount();

  return <div>Dark theme enforced</div>;
}

Important Implementation Details


Interaction with Other Parts of the System


Visual Diagram

classDiagram
    class ThemeProvider {
        +children: ReactNode
        +defaultTheme: ThemeEnum
        +storageKey: string
        +theme: ThemeEnum
        +setTheme(theme: ThemeEnum): void
    }
    class ThemeProviderContext {
        +theme: ThemeEnum
        +setTheme(theme: ThemeEnum): void
    }
    class useTheme {
        +(): ThemeProviderState
    }
    class useIsDarkTheme {
        +(): boolean
    }
    class useSwitchToDarkThemeOnMount {
        +(): void
    }

    ThemeProvider --> ThemeProviderContext : Provides context
    useTheme ..> ThemeProviderContext : Uses context
    useIsDarkTheme ..> useTheme : Uses hook
    useSwitchToDarkThemeOnMount ..> useTheme : Uses hook

Summary

The theme-provider.tsx file establishes a robust, React idiomatic way to manage and persist UI themes with minimal setup. It leverages React Context and hooks to expose theme state and functionality, applies the theme CSS class globally to the document root, and persists user preferences in localStorage. The provided hooks simplify theme consumption and control across the app, supporting light and dark modes seamlessly. This file is a key part of the UI infrastructure enabling consistent theming throughout the application.