Command Palette

Search for a command to run...

[ UI ]
Moon Icon

Theme Switcher

Beautiful theme switcher components with multiple variants

Overview

Six theme switcher variants for toggling between light and dark modes. Built with next-themes for hydration-safe rendering and smooth animations.

Components

Theme Switcher

Classic switch with fading sun/moon icons.

Theme Switcher Switch

Centered switch variant with smaller icons.

Theme Switcher Button

Icon button with rotating animation

Theme Switcher Dropdown

Menu with Light, Dark, and System options.

Theme Switcher Toggle

Custom toggle with sliding icon.

Theme Switcher Multi Button

Segmented control showing all options at once.

Installation

Install any variant:

bunx shadcn@latest add @elements/theme-switcher

Install all variants:

bunx shadcn@latest add @elements/theme-switcher @elements/theme-switcher-switch @elements/theme-switcher-button @elements/theme-switcher-dropdown @elements/theme-switcher-toggle @elements/theme-switcher-multi-button

Setup

1. Install next-themes

npm install next-themes

2. Configure ThemeProvider

import { ThemeProvider } from "next-themes";

export default function RootLayout({ children }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}

3. Configure Tailwind

module.exports = {
  darkMode: ["class"],
}

Usage

import { ThemeSwitcher } from "@/components/elements/theme-switcher";

export default function Header() {
  return (
    <header>
      <ThemeSwitcher />
    </header>
  );
}

Which Variant to Use?

VariantSystem SupportBest For
SwitcherNoHeaders, navbars
SwitchNoCompact spaces
ButtonNoToolbars
DropdownYesSettings pages
ToggleNoMobile UIs
Multi ButtonYesDashboards

Note: Only Dropdown and Multi Button support system theme preference.

Advanced

Programmatic Control

"use client";
import { useTheme } from "next-themes";

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

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

Responsive Usage

import { ThemeSwitcherButton } from "@/components/elements/theme-switcher-button";
import { ThemeSwitcherDropdown } from "@/components/elements/theme-switcher-dropdown";

export default function Nav() {
  return (
    <>
      <div className="md:hidden">
        <ThemeSwitcherButton />
      </div>
      <div className="hidden md:block">
        <ThemeSwitcherDropdown />
      </div>
    </>
  );
}

Troubleshooting

Theme not changing? Verify ThemeProvider wraps your app and attribute="class" is set.

Hydration warnings? Add suppressHydrationWarning to <html> tag.

System theme not working? Use Dropdown or Multi Button variants (others don't support system preference).