Eclipse
The next appearance crosses the page like an eclipse.
themeappearancemotion
Preview
Eclipse preview
Live · keyboard ready
When to use
- Marketing or showcase pages where the theme change should feel like an event.
- Layouts where a directional sweep across the page reads naturally.
When not to use
- Use theme-switch-rise for everyday product chrome where a calmer change fits.
- Use theme-switch-split when the button sits in the center and direction should not matter.
shadcn CLI
Also installs (2)
- manicat-foundation
- button
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "theme-switch-eclipse",
"type": "registry:ui",
"title": "Eclipse",
"description": "The next appearance crosses the page like an eclipse.",
"categories": [
"actions"
],
"dependencies": [
"lucide-react",
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json",
"https://manicat.viraza.net/r/button.json"
],
"files": [
{
"path": "registry/components/theme-switch/theme-switch.tsx",
"type": "registry:component",
"target": "@components/manicat/theme-switch/theme-switch.tsx"
},
{
"path": "registry/components/theme-switch/theme-switch.module.css",
"type": "registry:component",
"target": "@components/manicat/theme-switch/theme-switch.module.css"
},
{
"path": "registry/components/button/button.tsx",
"type": "registry:component",
"target": "@components/manicat/button/button.tsx"
},
{
"path": "registry/components/button/button.module.css",
"type": "registry:component",
"target": "@components/manicat/button/button.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/theme-switch-eclipse",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/theme-switch-eclipse",
"markdown": "https://uiarc.dev/components/theme-switch-eclipse/markdown",
"tags": [
"theme",
"appearance",
"motion"
]
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { useEffect, useState } from "react";
import { ThemeSwitch } from "@/components/manicat/theme-switch/theme-switch";
import { useTheme } from "fumadocs-ui/provider/base";
function useMounted() {
const [mounted, setMounted] = useState(false);
useEffect(() => {
const frame = requestAnimationFrame(() => setMounted(true));
return () => cancelAnimationFrame(frame);
}, []);
return mounted;
}
export function ThemeSwitchEclipseExample() {
const { resolvedTheme, setTheme } = useTheme();
const mounted = useMounted();
if (!mounted) return null;
return (
<ThemeSwitch
variant="eclipse"
theme={resolvedTheme === "dark" ? "dark" : "light"}
onThemeChange={(next) => setTheme(next)}
/>
);
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Eclipse The sun is eclipsed by the moon as the theme changes.
Eclipse
The sun is eclipsed by the moon as the theme changes. preview
Live · keyboard ready
eclipse-the-sun-is-eclipsed-by-the-moon-as-the-theme-changes-.tsxtsx
"use client";
import { useState } from "react";
import { ThemeSwitch } from "@/components/manicat/theme-switch/theme-switch";
export function ThemeSwitchEclipseHeaderExample() {
const [theme, setTheme] = useState<"light" | "dark">("dark");
return <ThemeSwitch variant="eclipse" theme={theme} onThemeChange={setTheme} />;
}
Keyboard interactions
| Keys | Action |
|---|---|
| Enter / Space | Toggles the theme. |
Accessibility
- Same button as theme-switch: aria-pressed reflects dark mode and the label names the next theme.
- Keep the eclipse sweep off for reduced motion and swap the theme directly.
Motion
- variant="eclipse": the next appearance crosses the page like an eclipse; run it in onThemeChange with a view transition.
- The icon shifts 2px left in dark mode to lean into the sweep.
- Reduced motion removes the nudge and swaps the icon with a fade.
Responsive behavior
- The labelled button fits a desktop top bar; pass iconOnly for a fixed 38px square on narrow headers and mobile.
- Hover styles apply only on hover-capable fine pointers, so touch taps do not leave a stuck hover state.
Performance
- The button itself is tiny: one icon swap on a spring, and the first theme after hydration applies without animating.
- The page transition is yours; a full-page view transition snapshots the whole document, so keep it short and skip it for reduced motion.
Notes for AI
- Select with variant="eclipse". The prop only styles the icon nudge and is passed back to onThemeChange; the page animation is your code.
- Pick eclipse for a dramatic, directional change on marketing or showcase pages; rise suits product chrome better.