# Fade In

The FadeIn component creates a smooth fade-in animation for its children when they enter the viewport.

- **Category:** Animation
- **Docs:** https://uibeats.com/docs/animation/fade-in
- **Registry:** https://uibeats.com/r/fade-in.json
- **License:** MIT
- **npm dependencies:** `motion`

## Installation

```bash
npx shadcn@latest add https://uibeats.com/r/fade-in.json
```

Or install the dependencies and copy the source below:

```bash
npm install motion
```

## When to use

The safest entrance animation, and the right default when you are unsure. Use it for body copy, images and anything below the fold that should feel considered rather than demand attention.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` | `React.ReactNode` | `-` | The content to be faded in (required) |
| `delay` | `number` | `0` | Delay before the animation starts (in seconds) |
| `duration` | `number` | `0.5` | Duration of the animation (in seconds) |
| `className` | `string` | `''` | Additional CSS classes for styling |
| `once` | `boolean` | `true` | Whether to trigger the animation only once |

## Example usage

```tsx
import React from "react";
import FadeIn from "@/components/demo/animation/fade-in";

const FadeInUsage = () => {
  return (
    <FadeIn delay={1.2}>
      <p className="text-md mb-4 md:text-lg">
        This content will fade in when it enters the viewport
      </p>
    </FadeIn>
  );
};

export default FadeInUsage;
```

## Source

Save as `components/ui/fade-in.tsx`.

```tsx
"use client";
import React from "react";
import {
  motion,
  useInView,
  useReducedMotion,
  type Variants,
} from "motion/react";

interface FadeInProps {
  children: React.ReactNode;
  delay?: number;
  duration?: number;
  className?: string;
  once?: boolean;
}

const FadeIn: React.FC<FadeInProps> = ({
  children,
  delay = 0,
  duration = 0.5,
  className = "",
  once = true,
}) => {
  const ref = React.useRef<HTMLDivElement>(null);
  const isInView = useInView(ref, { once, amount: 0.1 });
  const prefersReducedMotion = useReducedMotion();

  /*
   * A fade moves nothing, so this is the one entrance that could arguably be
   * left running. It is switched off anyway for a duller reason: the fade is
   * gated on `useInView`, and a reader who has asked for no motion should not
   * have to scroll content into view before it becomes readable.
   */
  const variants: Variants = prefersReducedMotion
    ? { hidden: { opacity: 1 }, visible: { opacity: 1 } }
    : {
        hidden: { opacity: 0 },
        visible: {
          opacity: 1,
          transition: {
            duration: duration,
            delay: delay,
            ease: "easeOut",
          },
        },
      };

  return (
    <motion.div
      ref={ref}
      initial="hidden"
      animate={isInView ? "visible" : "hidden"}
      variants={variants}
      className={className}
    >
      {children}
    </motion.div>
  );
};

export default FadeIn;
```

## Credits

Written by [Michael](https://github.com/lappemic).
