Join our Discord community
Special effects

Theme Toggle Button

Animated dark mode switch with View Transitions API. Beautiful theme toggles for React applications with multiple animation effects and Next.js integration.

Loading component...

Installation

npx shadcn@latest add https://www.shadcn.io/registry/theme-toggle-button.json
npx shadcn@latest add https://www.shadcn.io/registry/theme-toggle-button.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/theme-toggle-button.json
bunx shadcn@latest add https://www.shadcn.io/registry/theme-toggle-button.json

Features

  • Multiple animation variants including circle, blur, polygon and custom GIF masks
  • View Transitions API for smooth, hardware-accelerated theme switching
  • Flexible positioning with animations starting from center, corners, or edges
  • TypeScript support with complete interface definitions and IntelliSense
  • Accessible controls with proper ARIA labels and keyboard navigation
  • Framework agnostic works with any theme management solution

Use Cases

This free open source React component works well for:

  • Dark mode toggles - Elegant theme switching for Next.js applications
  • Settings interfaces - Beautiful preference controls using Tailwind CSS
  • Navigation bars - Eye-catching theme buttons with shadcn/ui integration
  • Landing pages - Memorable user experiences with custom animations

Usage

import {
  ThemeToggleButton,
  useThemeTransition,
} from "@/components/theme-toggle-button";
import { useTheme } from "next-themes";

export default function Example() {
  const { theme, setTheme } = useTheme();
  const { startTransition } = useThemeTransition();

  const handleToggle = () => {
    const newTheme = theme === "light" ? "dark" : "light";
    startTransition(() => {
      setTheme(newTheme);
    });
  };

  return <ThemeToggleButton theme={theme} onClick={handleToggle} />;
}

Examples

Basic Usage

The default variant uses a circle animation from the center:

<ThemeToggleButton theme={theme} onClick={handleToggle} />

With Label

Show a text label alongside the icon:

<ThemeToggleButton theme={theme} onClick={handleToggle} showLabel />

Animation Variants

Circle Animation

The circle variant creates an expanding circle mask effect:

// From center (default)
<ThemeToggleButton
  theme={theme}
  onClick={handleToggle}
  variant="circle"
/>

// From corners
<ThemeToggleButton
  theme={theme}
  onClick={handleToggle}
  variant="circle"
  start="top-left"
/>
<ThemeToggleButton
  theme={theme}
  onClick={handleToggle}
  variant="circle"
  start="bottom-right"
/>

Circle with Blur

Adds a gaussian blur to the circle edge for a softer transition:

<ThemeToggleButton
  theme={theme}
  onClick={handleToggle}
  variant="circle-blur"
  start="top-right"
/>

Polygon Animation

Creates a diagonal wipe effect using clip-path:

<ThemeToggleButton theme={theme} onClick={handleToggle} variant="polygon" />

Custom GIF Animation

Use any GIF as a mask for the transition:

<ThemeToggleButton
  theme={theme}
  onClick={handleToggle}
  variant="gif"
  url="https://media.giphy.com/media/your-gif-id/giphy.gif"
/>

API Reference

ThemeToggleButton

PropTypeDefaultDescription
theme'light' | 'dark''light'Current theme state
showLabelbooleanfalseShow text label next to icon
variant'circle' | 'circle-blur' | 'gif' | 'polygon''circle'Animation variant to use
start'center' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right''center'Starting position for circle animations
urlstringundefinedURL of GIF to use as mask (required for gif variant)
classNamestringundefinedAdditional CSS classes
onClick() => voidundefinedClick handler for theme toggle

Hooks

useThemeTransition

A helper hook that wraps the View Transitions API:

const { startTransition } = useThemeTransition();

// Use it to wrap your theme update
startTransition(() => {
  setTheme(newTheme);
  // Any other DOM updates
});

This hook automatically falls back to immediate updates in browsers that don't support the View Transitions API.

Browser Support

The View Transitions API is supported in:

  • Chrome/Edge 111+ with full animation support
  • Opera 97+ with complete feature set
  • Safari with flag enabled in Settings > Advanced > Feature Flags > View Transitions
  • Firefox not yet supported, gracefully falls back

Note: To see the animations, make sure you're using a supported browser. In Safari, you need to enable the View Transitions flag manually.

Implementation Notes

  • Component is UI-only, theme management handled externally
  • Animations inject CSS dynamically for optimal performance
  • Works with any theme solution (next-themes, custom context, etc.)
  • All animations use hardware acceleration when available
  • Cleanup handled automatically after transitions complete