Rise

The next appearance rises into place.

themeappearancemotion
Preview
Rise preview

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

Keyboard interactions

KeysAction
Enter / SpaceToggles 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.