Skip to main content

ThemeSwitcher

A dropdown menu component that allows users to switch between color themes and toggle between light/dark modes. Built with shadcn/ui components and fully integrated with next-themes.
Located in registry/nextjs/components/theme-switcher.tsx

Component Signature

Props

This component accepts no props. All configuration is handled internally through the useTheme hook.

Features

  • Dual Theme Controls: Separate controls for color theme and light/dark mode
  • Visual Theme Previews: Color dots showing each theme’s primary color
  • Current Theme Indicator: Check marks on active selections
  • Scrollable Theme List: Smooth scrolling for 45+ themes
  • SSR Safe: Prevents hydration mismatches with mounted state
  • Keyboard Accessible: Full keyboard navigation support

Usage

UI Structure

Trigger Button

Component
Ghost variant icon button (9×9) displaying Sun (light mode) or Moon (dark mode) icon.
The dropdown menu contains three main sections:

1. Current Theme Label

DropdownMenuLabel
Shows the current theme name with a colored preview dot.

2. Mode Toggle (Light/Dark)

DropdownMenuItem[]
Two items for switching between light and dark modes. Active mode shows a check mark.

3. Color Theme Submenu

DropdownMenuSub
Scrollable submenu with all 45 themes, each showing a color preview.

Internal Functions

parseTheme

Helper function to extract color theme and mode from theme string.
string | undefined
Theme string like "catppuccin-dark" or "vercel-light"
Returns:
string
Theme name without mode suffix (e.g., "catppuccin")
'light' | 'dark'
Extracted mode from theme string, defaults to "dark"
Examples:

setColorTheme

Sets the color theme while preserving the current mode.
Example:

setMode

Sets the light/dark mode while preserving the current color theme.
Example:

Hydration Safety

The component uses a mounted state to prevent hydration mismatches:
This ensures the server-rendered HTML matches the initial client render before showing the actual theme state.

Dependencies

Required Components (shadcn/ui)

  • Button - Trigger button component
  • DropdownMenu - Main menu container
  • DropdownMenuContent - Menu content wrapper
  • DropdownMenuItem - Individual menu items
  • DropdownMenuLabel - Menu section labels
  • DropdownMenuSeparator - Visual dividers
  • DropdownMenuSub - Nested submenu
  • DropdownMenuSubTrigger - Submenu trigger
  • DropdownMenuSubContent - Submenu content
  • DropdownMenuPortal - Portal for submenu rendering
  • ScrollArea - Scrollable theme list

Required Icons (lucide-react)

  • Sun - Light mode icon
  • Moon - Dark mode icon
  • Palette - Theme picker icon
  • Check - Active selection indicator

Required Utilities

  • useTheme from next-themes - Theme state management
  • cn from @/lib/utils - Class name utility
  • sortedThemes from @/lib/themes-config - Sorted theme list
  • themes from @/lib/themes-config - Theme configurations

Styling

The component uses Tailwind CSS classes and is fully customizable:

Accessibility

  • Screen Reader Support: Trigger button includes <span class="sr-only">Toggle theme</span>
  • Keyboard Navigation: Full keyboard support via DropdownMenu
  • Visual Indicators: Check marks for active selections
  • Color Previews: Visual dots help users identify themes

Advanced Customization

Custom Button Styling

Wrap and style the component:

Fork for Custom Behavior

Copy and modify the component to:
  • Filter visible themes
  • Add custom theme groupings
  • Change icon sets
  • Modify menu structure
theme-switcher-custom.tsx

See Also