Skip to content

Instantly share code, notes, and snippets.

@johnpolacek
Last active October 2, 2024 08:21
Show Gist options
  • Save johnpolacek/c7ddd607a4d5dbf43f38ae7266f6de18 to your computer and use it in GitHub Desktop.
Save johnpolacek/c7ddd607a4d5dbf43f38ae7266f6de18 to your computer and use it in GitHub Desktop.
Utility React UI Component for animating elements in with Tailwind and CSS Animation and plays nicely with shadcn
import React, { useEffect, useState } from "react";
import cn from "mxcn";
// or if using shadcn:
// import { cn } from "@/lib/utils"; // https://github.com/shadcn-ui/ui/blob/main/apps/www/lib/utils.ts
const AnimateIn = ({
children,
delay = 0,
duration = 500,
className = "",
from,
to,
style,
as = 'div',
}: {
from: string;
to: string;
children?: React.ReactNode;
delay?: number;
duration?: number;
className?: string;
style?: React.CSSProperties;
as?: keyof React.ReactHTML;
}) => {
const [animate, setAnimate] = useState(from);
const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);
useEffect(() => {
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
const mediaQueryChangeHandler = (e: MediaQueryListEvent) => {
setPrefersReducedMotion(e.matches);
};
setPrefersReducedMotion(mediaQuery.matches);
mediaQuery.addEventListener('change', mediaQueryChangeHandler);
return () => {
mediaQuery.removeEventListener('change', mediaQueryChangeHandler);
};
}, []);
useEffect(() => {
if (prefersReducedMotion) {
// If the user prefers reduced motion, skip the animation
setAnimate(to);
return;
}
const timer = setTimeout(() => {
setAnimate(to);
}, delay);
return () => clearTimeout(timer);
}, [delay, to, prefersReducedMotion]);
return React.createElement(
as,
{
className: cn("transition-all ease-in-out", className, animate),
style: { transitionDuration: prefersReducedMotion ? "0ms" : `${duration}ms`, ...style},
},
children
);
};
export default AnimateIn;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment