Skip to content

ReducedMotionToggle

SM, under 950B gzipped

An in-page opt-in to reduced motion, for people who never touch OS settings.

Category
Accessibility & preferences
Budget
sm, single-purpose control
Runtime deps
None

Preview

Preview language

This is the exact fixture the conformance suite renders in CI. Switch the language to see the component mirror and reformat.

Install

npx shadcn@latest add https://kata-ui-rho.vercel.app/r/reduced-motion-toggle.json

Copies the source into your project. Pulls in 3 primitives: switch, cn, use-stored-value.

Source

"use client";

import { useEffect } from "react";
import { useStoredValue } from "../lib/use-stored-value";
import { Switch } from "./switch";

const STORAGE_KEY = "anywhere-ui:reduce-motion";

/**
 * Lets someone opt into reduced motion from inside the page, for the many
 * people who have never touched their OS accessibility settings but still
 * find animation distracting or nausea-inducing. Setting this data attribute
 * is a contract: consuming CSS should treat `[data-reduce-motion="true"]` the
 * same as `prefers-reduced-motion: reduce`.
 */
export function ReducedMotionToggle({ label = "Reduce motion" }: { label?: string }) {
  const [stored, setStored] = useStoredValue(STORAGE_KEY, "false");
  const reduced = stored === "true";

  useEffect(() => {
    document.documentElement.dataset.reduceMotion = String(reduced);
  }, [reduced]);

  return <Switch checked={reduced} onCheckedChange={(v) => setStored(String(v))} label={label} />;
}

What CI checks

← All components