# Gradient Flow

The GradientFlow component creates a flowing gradient animation effect for its children, adding visual interest to backgrounds or UI elements.

- **Category:** Background
- **Docs:** https://uibeats.com/docs/background/gradient-flow
- **Registry:** https://uibeats.com/r/gradient-flow.json
- **License:** MIT
- **npm dependencies:** `motion`

## Installation

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

Or install the dependencies and copy the source below:

```bash
npm install motion
```

## When to use

A calm, always-moving backdrop for heroes and call-to-action sections. Because it never settles, keep it behind large type and avoid placing dense body copy on top of it.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` | `React.ReactNode` | `-` | The content to be wrapped with the gradient flow effect (required) |
| `duration` | `number` | `10` | Duration of the animation cycle (in seconds) |
| `colors` | `string[]` | `['#ff0080', '#7928ca', '#ff4d4d']` | Array of colors to use in the gradient |
| `className` | `string` | `''` | Additional CSS classes for styling |

## Example usage

```tsx
import React from "react";
import GradientFlow from "@/components/demo/background/gradient-flow";

const GradientFlowUsage = () => {
  return (
    <GradientFlow
      duration={20}
      colors={["#6366f1", "#2563eb", "#7c3aed", "#db2777"]}
      fullWidth={true}
      radialOverlay={true}
      blurAmount="10px"
    >
      <div className="text-md mb-4 text-white md:text-lg">
        Flowing Gradient Background
      </div>
    </GradientFlow>
  );
};

export default GradientFlowUsage;
```

## Source

Save as `components/ui/gradient-flow.tsx`.

```tsx
"use client";

import React from "react";
import { motion, useReducedMotion } from "motion/react";

interface GradientFlowProps {
  children: React.ReactNode;
  duration?: number;
  colors?: string[];
  className?: string;
  fullWidth?: boolean;
  radialOverlay?: boolean;
  blurAmount?: string;
}

const GradientFlow: React.FC<GradientFlowProps> = ({
  children,
  duration = 20,
  colors = ["#6366f1", "#2563eb", "#7c3aed", "#db2777"],
  className = "",
  fullWidth = false,
  radialOverlay = true,
  blurAmount = "10px",
}) => {
  const prefersReducedMotion = useReducedMotion();

  const gradientString = `linear-gradient(135deg, ${colors.join(", ")})`;
  const radialGradient =
    "radial-gradient(circle at 50% 50%, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 70%)";

  return (
    <div
      className={`relative overflow-hidden ${
        fullWidth ? "h-full w-full" : ""
      } ${className}`}
    >
      <motion.div
        className="absolute inset-0"
        style={{
          backgroundImage: gradientString,
          backgroundSize: "400% 400%",
          filter: `blur(${blurAmount})`,
        }}
        /*
         * The gradient still renders under reduced motion, it just stops
         * travelling. This is a decorative backdrop that content sits on top
         * of, so removing it outright would change the contrast behind the
         * children rather than only calming the page.
         */
        animate={
          prefersReducedMotion
            ? undefined
            : { backgroundPosition: ["0% 0%", "100% 100%", "0% 0%"] }
        }
        transition={
          prefersReducedMotion
            ? undefined
            : {
                duration: duration,
                repeat: Infinity,
                ease: "easeInOut",
              }
        }
      />
      {radialOverlay && (
        <div
          className="absolute inset-0"
          style={{
            backgroundImage: radialGradient,
            mixBlendMode: "overlay",
          }}
        />
      )}
      <div className="relative z-10 flex h-full w-full items-center justify-center backdrop-blur-sm">
        {children}
      </div>
    </div>
  );
};

export default GradientFlow;
```

## Credits

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