Theme Toggle

Accessible dark mode toggle with View Transitions API support. Icon, icon-label, or dual-tab variants.

Component

Icon

Icon with label

Dual tabs

Installation

pnpm dlx shadcn@latest add "https://pulkitxm.com/components/theme-toggle.json"

After running the command

Complete these steps to finish the setup:

1. Import theme transition CSS in globals.css
/* Add to app/globals.css: */
@import "./theme-toggle.css";
2. Wrap app with ThemeProvider
import { ThemeProvider } from "@/providers/theme-provider";

export default function RootLayout({ children }) {
  return (
    <html suppressHydrationWarning>
      <body>
        <ThemeProvider
          attribute="class"
          defaultTheme="system"
          enableSystem
        >
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}
3. Import and use
import { ThemeToggle } from "@/components/theme-toggle";

<ThemeToggle />;

Usage

Import the component

Add the ThemeToggle import to your file.

import { ThemeToggle } from "@/components/theme-toggle";

Use with default props

Use the default icon-only toggle in your navbar or header.

<ThemeToggle />;

Customize with props

Use simple for icon + label, or dual for tab-style selection.

<ThemeToggle simple />;

Guidelines

  • Wrap your app with ThemeProvider from providers/theme-provider before using ThemeToggle. Place it inside <body>, not wrapping it.
  • For Tailwind v4, add @custom-variant dark (&:is(.dark *)); to globals.css for class-based dark mode.
  • ThemeProvider must be inside body. Add suppressHydrationWarning to the html tag.
  • For smooth theme transitions, import theme-toggle.css in globals.css.
  • Hold Ctrl or Cmd while clicking to skip the view transition (useful for testing).

Props

PropTypeDefaultDescription
simplebooleanfalseShow icon with Light/Dark label next to it.
dualbooleanfalseRender as dual-tab layout with Light and Dark options.
classNamestringundefinedAdditional CSS classes for the toggle.
useViewTransitionbooleantrueUse View Transitions API for theme switch animation when supported.
children(theme: { theme: 'light' | 'dark'; toggleTheme: () => void }) => React.ReactNodeundefinedRender prop receiving { theme, toggleTheme } for custom UI.

Examples

Icon

Icon-only toggle. Compact for navbars and headers.

Icon

Icon with label

Dual tabs

import { ThemeToggle } from "@/components/theme-toggle";

export function ThemeToggleBasic() {
  return <ThemeToggle />;
}

Icon with label

Icon with Light/Dark label. Useful for mobile or settings.

Icon

Icon with label

Dual tabs

import { ThemeToggle } from "@/components/theme-toggle";

export function ThemeToggleWithLabel() {
  return <ThemeToggle simple />;
}

Dual tabs

Dual-tab layout with Light and Dark options side by side.

Icon

Icon with label

Dual tabs

import { ThemeToggle } from "@/components/theme-toggle";

export function ThemeToggleDual() {
  return <ThemeToggle dual />;
}

Made with ❤️ by Pulkit

© 2026 Pulkit. All rights reserved

DMCA Verified

Last updated: