# Fade In Unblur

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

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

## Installation

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

Or install the dependencies and copy the source below:

```bash
npm install motion
```

## When to use

A fade with a defocus-to-focus feel, which buys a moment of anticipation. Good for hero imagery and product screenshots; too heavy for repeated list items, where the blur becomes tiring.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` | `React.ReactNode` | `-` | The content to be faded in unblurred (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 FadeInUnblur from "@/components/demo/animation/fade-in-unblur";

const FadeInUnblurUsage = () => {
  return (
    <FadeInUnblur delay={1.2}>
      <p className="text-md mb-4 md:text-lg">
        This content fades in while unblurring when it enters the viewport
      </p>
    </FadeInUnblur>
  );
};

export default FadeInUnblurUsage;
```

## Source

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

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

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

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

  /*
   * The settled state keeps `scale: 1.2`, which is where the animation ends,
   * and matching it is the point. Reducing it to 1 here would render the
   * component at a different size for these users than for everyone else.
   */
  const variants: Variants = prefersReducedMotion
    ? {
        hidden: { opacity: 1, scale: 1.2, filter: "blur(0px)" },
        visible: { opacity: 1, scale: 1.2, filter: "blur(0px)" },
      }
    : {
        hidden: {
          opacity: 0,
          scale: 1.1,
          filter: "blur(4px)",
        },
        visible: {
          opacity: 1,
          scale: 1.2,
          filter: "blur(0px)",
          transition: {
            duration: duration,
            delay: delay,
            ease: [0.47, 0, 0.745, 0.715],
          },
        },
      };

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

export default FadeInUnblur;
```

## Credits

Written by [Divyaswor](https://github.com/divyaswormakai).
