{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "progressive-blur",
  "title": "Progressive Blur",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "A blur that ramps up toward an edge instead of switching on at a line, made of stacked backdrop-filter layers, for scrolling lists, headers, footers and image captions.",
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ballmac/components/progressive-blur.tsx",
      "content": "// Ballmac UI: Progressive Blur. https://ui.ballmac.com/components/progressive-blur\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype ProgressiveBlurProps = Omit<React.ComponentProps<\"div\">, \"children\"> & {\n  /** Edge the blur is attached to. It is strongest right at the edge. */\n  position?: \"top\" | \"bottom\" | \"left\" | \"right\"\n  /** Depth of the blurred band: a CSS length such as \"6rem\" or \"30%\". */\n  size?: string\n  /** Strongest blur in pixels, reached at the edge. */\n  strength?: number\n  /** Number of stacked layers. More layers make a smoother ramp and cost a little more to paint. */\n  layers?: number\n}\n\n// The gradient runs from the inner edge of the band toward the attached edge, where the blur is strongest.\nconst TO = { top: \"to top\", bottom: \"to bottom\", left: \"to left\", right: \"to right\" } as const\n\n/**\n * A blur that ramps up toward an edge instead of switching on at a line, made from stacked\n * backdrop-filter layers with staggered masks. Pointer events pass through it. Decorative.\n */\nfunction ProgressiveBlur({ position = \"bottom\", size = \"5rem\", strength = 14, layers = 8, className, style, ...props }: ProgressiveBlurProps) {\n  const horizontal = position === \"left\" || position === \"right\"\n  const n = Math.max(2, Math.min(layers, 12))\n  return (\n    <div\n      data-slot=\"progressive-blur\"\n      aria-hidden=\"true\"\n      className={cn(\"pointer-events-none absolute z-10\", horizontal ? \"inset-y-0\" : \"inset-x-0\", className)}\n      style={{ [position]: 0, [horizontal ? \"width\" : \"height\"]: size, ...style }}\n      {...props}\n    >\n      {Array.from({ length: n }, (_, i) => {\n        // Each layer fades in over a window of the band and is blurred a little more than the one before.\n        const from = (i * 100) / (n + 1)\n        const blur = (strength * (i + 1)) / n\n        const mask = `linear-gradient(${TO[position]}, transparent ${from}%, black ${from + 100 / (n + 1)}%, black ${from + 200 / (n + 1)}%, transparent ${from + 300 / (n + 1)}%)`\n        return (\n          <span\n            key={i}\n            className=\"absolute inset-0\"\n            style={{\n              backdropFilter: `blur(${blur.toFixed(2)}px)`,\n              WebkitBackdropFilter: `blur(${blur.toFixed(2)}px)`,\n              maskImage: mask,\n              WebkitMaskImage: mask,\n            }}\n          />\n        )\n      })}\n    </div>\n  )\n}\n\nexport { ProgressiveBlur, type ProgressiveBlurProps }\n",
      "type": "registry:ui",
      "target": "@components/ballmac/progressive-blur.tsx"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "blur",
      "gradient",
      "edge",
      "scroll",
      "backdrop"
    ],
    "version": "1.0.0",
    "updated": "2026-10-01",
    "ai": {
      "summary": "<ProgressiveBlur position='top|bottom|left|right' size strength layers /> inside a relative parent that scrolls or holds an image. Pointer events pass through it. A server component with no JavaScript.",
      "whenToUse": [
        "Scrolling lists that fade out at the edges",
        "Text over images, instead of a dark gradient"
      ],
      "whenNotToUse": [
        "Browsers or surfaces without backdrop-filter support (it degrades to no blur)"
      ],
      "composesWith": [
        "scroll-area",
        "card"
      ],
      "a11y": [
        {
          "keys": "Screen readers",
          "action": "Decorative: aria-hidden and pointer-events-none"
        },
        {
          "keys": "Interaction",
          "action": "Never blocks clicks or scrolling"
        }
      ],
      "customization": [
        "position",
        "size",
        "strength",
        "layers"
      ]
    },
    "examples": [
      "progressive-blur-demo",
      "progressive-blur-sides"
    ],
    "url": "https://ui.ballmac.com/components/progressive-blur"
  },
  "categories": [
    "motion"
  ],
  "type": "registry:ui"
}