Skip to content
Template Empire / components

Search components

10 results

Browse components

Theme Wipe

A free animated theme switcher for React and Next.js with a circular wipe reveal.

  • Automated axe check
  • Reduced-motion tested
  • SSR build verified
  • Motion
  • 2 runtime packages

Theme Wipe is a free animated theme switcher for React and Next.js, built with Motion and styled with Tailwind. Press the toggle and the incoming theme expands as a clip-path circle from the button itself until it covers the whole container, then the region flips its scoped data-theme and the overlay unmounts. Content never moves during the wipe; only the clip-path animates.

The component is fully controlled: you own the theme value and it calls onToggle with the next theme. Theming stays scoped to the wrapper through a data-theme attribute, and both themes reuse the same two semantic tokens with background and foreground swapped, so text contrast holds in either direction. Toggling again mid-wipe cancels cleanly, and with reduced motion enabled the theme flips instantly with no wipe at all.

Appearance

A reading surface that follows the light

Flip the toggle in the corner and the incoming theme sweeps across this panel from the button itself. The text never moves; the new palette simply washes over it.

Both themes are the same two semantic tokens with background and foreground swapped, so contrast holds in either direction.

Install

Add the @te registry to your components.json once:

{
  "registries": {
    "@te": "https://templateempire.io/r/{name}.json"
  }
}

Then install the component:

npx shadcn@latest add @te/theme-wipe

Usage

"use client";

import { useState } from "react";
import { ThemeWipe, type ThemeWipeTheme } from "@/components/theme-wipe";

export default function Page() {
  const [theme, setTheme] = useState<ThemeWipeTheme>("dark");

  return (
    <ThemeWipe theme={theme} onToggle={setTheme} className="rounded-2xl p-8">
      <h2 className="text-2xl font-semibold">Appearance</h2>
      <p className="mt-2 opacity-80">
        The new theme sweeps across this panel from the toggle button.
      </p>
    </ThemeWipe>
  );
}

Props

PropTypeDefaultDescription
theme"light" | "dark"requiredControlled current theme.
onToggle(next: "light" | "dark") => voidrequiredCalled with the next theme when the toggle is pressed.
childrenReactNoderequiredThemed region the wipe plays across.
durationnumber0.6Wipe duration in seconds.
classNamestringundefinedAdditional classes merged onto the wrapper.

Customisation

Theme Wipe declares no tokens of its own. Both themes are the global background and foreground semantic tokens, painted as authored for dark and swapped for light, so retheming the tokens rethemes both sides of the wipe at once. Slow the reveal down with the duration prop and shape the panel from the className prop, which the overlay mirrors so the wipe always lines up:

<ThemeWipe
  theme={theme}
  onToggle={setTheme}
  duration={0.9}
  className="rounded-3xl p-10"
>
  {content}
</ThemeWipe>

/* retheme both sides of the wipe */
:root {
  --background: oklch(0.16 0.02 280);
  --foreground: oklch(0.97 0.01 280);
}

Frequently asked questions

Is Theme Wipe free for commercial use?
Yes. Theme Wipe is MIT licensed, so you can use it in personal and commercial projects without attribution.
Does Theme Wipe affect performance or accessibility?
The wipe animates clip-path on one overlay layer and nothing else, so content never moves and layout shift is zero. The toggle is a real button whose accessible name announces the theme a press will deliver, the overlay is aria-hidden, inert and pointer-events-none so your content stays interactive throughout, and theming is scoped to the wrapper rather than the page. With reduced motion enabled no overlay is ever created: the theme flips instantly with at most a 150ms colour fade.
Can I change how fast the wipe expands?
Yes. The duration prop sets the wipe length in seconds and defaults to 0.6. The circle always starts at the toggle button and grows to the farthest corner of the wrapper on the library easing curve, so a longer duration simply makes the same sweep more deliberate. Cancelling mid-wipe reverses the circle back into the button at the same pace.

Related components

Want the full page this belongs to?Template Empire builds complete Next.js templates with this motion system throughout. Browse the paid templates that pair with these free components.Explore Template Empire templates