Skip to content
38

useReducedMotion

Live prefers-reduced-motion match without an animation library. Renders false on the server, so hydration never mismatches, and updates when the setting changes.

Example

Installation

npx shadcn@latest add https://hirael.com/r/use-reduced-motion.json

Usage

import { useReducedMotion } from "@/hooks/use-reduced-motion"

Paths assume the default @/ alias from your components.json.

API

useReducedMotion()

Takes no arguments.

Returnsboolean

Source

import * as React from 'react';

const REDUCED_MOTION = '(prefers-reduced-motion: reduce)';

const subscribe = (onStoreChange: () => void) => {
  const query = window.matchMedia(REDUCED_MOTION);
  query.addEventListener('change', onStoreChange);

  return () => query.removeEventListener('change', onStoreChange);
};

/** Live `prefers-reduced-motion` match. The server and hydration render read `false`. */
export const useReducedMotion = () =>
  React.useSyncExternalStore(
    subscribe,
    () => window.matchMedia(REDUCED_MOTION).matches,
    () => false,
  );

Shipped