Inputs/Theme Toggle

Theme Toggle

Animated theme switcher with View Transitions API for smooth light/dark mode.

Themed

When to Use

Use Theme Toggle when you need to:

  • Allow users to switch between light and dark color modes
  • Provide a visually polished theme transition with animation
  • Add a persistent theme control in headers, sidebars, or settings panels
  • Leverage the View Transitions API for smooth full-page transitions

When Not to Use

  • For generic on/off states - use Toggle or Switch
  • When you need more than two theme options - build a custom theme selector with Button and a dropdown
  • For system-preference-only theming without manual control - use CSS prefers-color-scheme directly

Default

The default theme toggle with circle animation variant.

Click to toggle theme

Animation Variants

Four transition styles using the View Transitions API: circle, circle-blur, polygon, and instant.

circle
circle-blur
polygon
instant

Start Positions

Control the origin point for circle and circle-blur animations. The transition expands from the specified position.

center
top-left
top-right
bottom-left
bottom-right

With Label

Display a text label alongside the icon showing the current theme name.

Disabled

Disabled state prevents interaction and applies reduced opacity styling.

UX & Design Guidelines

Visual Hierarchy

The theme toggle uses a ghost button variant to remain visually unobtrusive. Place it in secondary UI areas such as headers, toolbars, or settings panels rather than as a primary action. The Sun and Moon icons provide immediate recognition of the toggle purpose.

Spacing & Layout

The icon-only variant renders as a size-9 (36px) square button, making it consistent with other icon buttons. When using showLabel, the button expands to default size with gap-2 spacing between icon and text. Group with other toolbar controls using consistent gap values.

Responsive Behavior

On smaller screens, prefer the icon-only variant without showLabel to conserve horizontal space. The 36px touch target meets minimum requirements for mobile interaction. Consider hiding the toggle on mobile layouts where space is limited and exposing it in a settings menu instead.

Color & Contrast

The toggle inherits the ghost variant styling, ensuring icon contrast against both light and dark backgrounds. The icon transition between Sun and Moon uses rotation and scale animations for a polished feel. The View Transitions API animation works across the full viewport, so test both themes for contrast compliance.

Accessibility

Keyboard Navigation

  • Tab — Move focus to/from the toggle button
  • Enter or Space — Activate the toggle to switch themes

Screen Reader Support

  • Provides dynamic aria-label that updates with the target theme (e.g., "Switch to light mode")
  • Includes a sr-only span with "Toggle theme" text for additional context
  • When showLabel is enabled, visible text provides supplementary information
  • Disabled state is announced via the native disabled attribute

Focus Management

Inherits the Button component's focus ring with focus-visible:ring-[3px]. Focus is preserved after the theme transition completes. The View Transitions API does not disrupt focus state, so users can continue navigating after toggling.

Motion Preferences

When the user has prefers-reduced-motion enabled, consider using the instant variant to skip view transition animations. Browsers that do not support the View Transitions API automatically fall back to an instant toggle with no animation.

ARIA Attributes

{/* Default — aria-label is set automatically */}
<ThemeToggle />
{/* Renders as: */}
<button aria-label="Switch to light mode">
  <Moon className="size-5" />
  <span className="sr-only">Toggle theme</span>
</button>

{/* With label — visible text provides context */}
<ThemeToggle showLabel />
{/* Renders as: */}
<button aria-label="Switch to dark mode">
  <Sun className="size-5" />
  <span>Light</span>
  <span className="sr-only">Toggle theme</span>
</button>

{/* Disabled — disabled attribute prevents interaction */}
<ThemeToggle disabled />

API Reference

The ThemeToggle component accepts the following props in addition to standard button attributes.

PropTypeDefaultDescription
variant"circle" | "circle-blur" | "polygon" | "instant""circle"The animation style used for the theme transition. Uses the View Transitions API.
start"center" | "top-left" | "top-right" | "bottom-left" | "bottom-right""center"The origin position for circle and circle-blur animations.
showLabelbooleanfalseWhen true, displays a text label ("Light" or "Dark") next to the icon.
disabledbooleanfalseWhen true, prevents user interaction and applies disabled styles.
classNamestringAdditional CSS classes to apply to the toggle button.