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

All props are optional unless marked required. Use these to customize every aspect of the component.

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 & Cursor :)

© 2026 Pulkit. All rights reserved

DMCA Verified

Last updated: