fade-in.tsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. "use client";
  2. import { motion, useReducedMotion } from "framer-motion";
  3. import { ReactNode } from "react";
  4. interface FadeInProps {
  5. children: ReactNode;
  6. delay?: number;
  7. className?: string;
  8. }
  9. export function FadeIn({ children, delay = 0, className = "" }: FadeInProps) {
  10. const reduceMotion = useReducedMotion();
  11. return (
  12. <motion.div
  13. initial={
  14. reduceMotion
  15. ? { opacity: 1, y: 0 }
  16. : { opacity: 0, y: 12, filter: "blur(2px)" }
  17. }
  18. whileInView={
  19. reduceMotion
  20. ? { opacity: 1, y: 0 }
  21. : { opacity: 1, y: 0, filter: "blur(0px)" }
  22. }
  23. viewport={{ once: true, amount: 0.2 }}
  24. transition={{
  25. duration: 0.42,
  26. delay,
  27. ease: [0.16, 1, 0.3, 1],
  28. }}
  29. className={className}
  30. style={{ willChange: "opacity, transform, filter" }}
  31. >
  32. {children}
  33. </motion.div>
  34. );
  35. }
  36. interface FadeInStaggerProps {
  37. children: ReactNode;
  38. className?: string;
  39. }
  40. export function FadeInStagger({ children, className = "" }: FadeInStaggerProps) {
  41. const reduceMotion = useReducedMotion();
  42. return (
  43. <motion.div
  44. initial="hidden"
  45. whileInView="visible"
  46. viewport={{ once: true, amount: 0.2 }}
  47. variants={{
  48. hidden: reduceMotion ? { opacity: 1 } : { opacity: 0 },
  49. visible: {
  50. opacity: 1,
  51. transition: {
  52. staggerChildren: reduceMotion ? 0 : 0.06,
  53. delayChildren: reduceMotion ? 0 : 0.03,
  54. },
  55. },
  56. }}
  57. className={className}
  58. >
  59. {children}
  60. </motion.div>
  61. );
  62. }
  63. interface FadeInItemProps {
  64. children: ReactNode;
  65. className?: string;
  66. }
  67. export function FadeInItem({ children, className = "" }: FadeInItemProps) {
  68. const reduceMotion = useReducedMotion();
  69. return (
  70. <motion.div
  71. variants={{
  72. hidden: reduceMotion ? { opacity: 1, y: 0 } : { opacity: 0, y: 10, filter: "blur(2px)" },
  73. visible: reduceMotion ? { opacity: 1, y: 0 } : { opacity: 1, y: 0, filter: "blur(0px)" },
  74. }}
  75. transition={{ duration: 0.38, ease: [0.16, 1, 0.3, 1] }}
  76. className={className}
  77. style={{ willChange: "opacity, transform, filter" }}
  78. >
  79. {children}
  80. </motion.div>
  81. );
  82. }