Rise
The next appearance rises into place.
themeappearancemotion
Preview
Rise preview
Live · keyboard ready
When to use
- Product chrome and dashboards where the theme change should be calm.
- Icon-only toggles in a top bar, as the library's own header uses it.
When not to use
- Use theme-switch-eclipse for a dramatic change on a showcase page.
- Use user-menu when theme belongs with account settings.
shadcn CLI
Also installs (2)
- manicat-foundation
- button
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "theme-switch-rise",
"type": "registry:ui",
"title": "Rise",
"description": "The next appearance rises into place.",
"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-rise",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/theme-switch-rise",
"markdown": "https://uiarc.dev/components/theme-switch-rise/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 ThemeSwitchRiseExample() {
const { resolvedTheme, setTheme } = useTheme();
const mounted = useMounted();
if (!mounted) return null;
return (
<ThemeSwitch
variant="rise"
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.
Rise The new theme rises from the bottom of the control.
Rise
The new theme rises from the bottom of the control. preview
Live · keyboard ready
rise-the-new-theme-rises-from-the-bottom-of-the-control-.tsxtsx
"use client";
import { useState } from "react";
import { ThemeSwitch } from "@/components/manicat/theme-switch/theme-switch";
export function ThemeSwitchRiseHeaderExample() {
const [theme, setTheme] = useState<"light" | "dark">("light");
return <ThemeSwitch variant="rise" 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 rise off for reduced motion and swap the theme directly.
Motion
- variant="rise": the next appearance rises into place from the bottom; run it in onThemeChange with a view transition.
- The icon lifts 2px in dark mode.
- 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="rise". The prop only styles the icon nudge and is passed back to onThemeChange; the page animation is your code.
- The calmest of the four; the library's own top bar uses it with iconOnly.