{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "shimmer-text",
  "title": "Shimmer Text",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "Text with a band of light sweeping across it, from muted to full foreground color. Suited to AI \"thinking\" and loading status lines; static under reduced motion.",
  "dependencies": [
    "motion@^12"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ballmac/components/shimmer-text.tsx",
      "content": "// Ballmac UI: Shimmer Text. https://ui.ballmac.com/components/shimmer-text\n\"use client\"\n\nimport * as React from \"react\"\nimport { animate, useReducedMotion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype ShimmerTextElement = \"span\" | \"p\" | \"div\" | \"h1\" | \"h2\" | \"h3\" | \"h4\"\n\ntype ShimmerTextProps = React.ComponentProps<\"span\"> & {\n  /** The element to render. Defaults to \"span\". */\n  as?: ShimmerTextElement\n  /** Seconds for one sweep across the text. */\n  duration?: number\n  /** Half-width of the highlight in em, so it scales with the font size. */\n  spread?: number\n}\n\nfunction ShimmerText({\n  as = \"span\",\n  duration = 2,\n  spread = 2,\n  className,\n  style,\n  children,\n  ...props\n}: ShimmerTextProps) {\n  const Comp = as as React.ElementType\n  const ref = React.useRef<HTMLElement>(null)\n  const reduceMotion = useReducedMotion()\n\n  React.useEffect(() => {\n    const node = ref.current\n    if (!node || reduceMotion) return\n    // The gradient is 250% wide: at 100% the highlight sits left of the text, at 0% right of it.\n    const controls = animate(\n      node,\n      { backgroundPosition: [\"100% 0%\", \"0% 0%\"] },\n      { duration, ease: \"linear\", repeat: Infinity }\n    )\n    return () => {\n      controls.stop()\n      node.style.backgroundPosition = \"\"\n    }\n  }, [duration, reduceMotion])\n\n  return (\n    <Comp\n      ref={ref}\n      data-slot=\"shimmer-text\"\n      className={cn(\n        \"inline-block bg-clip-text bg-no-repeat text-transparent forced-colors:bg-none forced-colors:text-[CanvasText]\",\n        className\n      )}\n      style={{\n        // Outside the highlight the text is --muted-foreground, which keeps body-text contrast.\n        backgroundImage: `linear-gradient(90deg, var(--muted-foreground) calc(50% - ${spread}em), var(--foreground) 50%, var(--muted-foreground) calc(50% + ${spread}em))`,\n        backgroundSize: \"250% 100%\",\n        backgroundPosition: \"100% 0%\",\n        ...style,\n      }}\n      {...props}\n    >\n      {children}\n    </Comp>\n  )\n}\n\nexport { ShimmerText, type ShimmerTextProps }\n",
      "type": "registry:ui",
      "target": "@components/ballmac/shimmer-text.tsx"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "text",
      "loading",
      "ai",
      "status",
      "shimmer",
      "motion"
    ],
    "version": "1.0.0",
    "updated": "2026-09-28",
    "ai": {
      "summary": "Wrap short text: <ShimmerText>Thinking…</ShimmerText>. The base color is --muted-foreground, so the text stays readable at every frame; the sweep brightens it to --foreground. In forced-colors mode it falls back to plain system text.",
      "whenToUse": [
        "An AI assistant's \"Thinking…\" or \"Searching the docs…\" line while a response streams",
        "Inline pending states such as \"Deploying…\" or \"Indexing 1,204 files\"",
        "A subtle accent on a short marketing label"
      ],
      "whenNotToUse": [
        "Paragraphs or long text (the sweep becomes distracting)",
        "The only signal that something is loading; pair it with aria-live or a spinner's label for screen readers"
      ],
      "composesWith": [
        "text-reveal",
        "border-beam"
      ],
      "a11y": [],
      "customization": [
        "duration: seconds per sweep (default 2)",
        "spread: highlight half-width in em (default 2)",
        "as: span | p | div | h1–h4; size and weight via className",
        "Colors come from --muted-foreground and --foreground; override backgroundImage via style for other tokens"
      ]
    },
    "examples": [
      "shimmer-text-demo"
    ],
    "url": "https://ui.ballmac.com/components/shimmer-text"
  },
  "categories": [
    "motion"
  ],
  "type": "registry:ui"
}