{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "pulse-button",
  "title": "Pulse Button",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "A call-to-action button that sends soft rings outward to ask for attention, calming as soon as it is hovered or focused, and switchable off once the person acts.",
  "dependencies": [
    "motion@^12"
  ],
  "registryDependencies": [
    "utils",
    "https://ui.ballmac.com/r/button.json"
  ],
  "files": [
    {
      "path": "registry/ballmac/components/pulse-button.tsx",
      "content": "// Ballmac UI: Pulse Button. https://ui.ballmac.com/components/pulse-button\n\"use client\"\n\nimport * as React from \"react\"\nimport { motion, useReducedMotion } from \"motion/react\"\n\nimport { Button, type ButtonProps } from \"@/components/ballmac/button\"\nimport { cn } from \"@/lib/utils\"\n\ntype PulseTone = \"primary\" | \"chart-1\" | \"chart-2\" | \"chart-3\" | \"chart-4\" | \"chart-5\" | \"destructive\"\n\nconst RING: Record<PulseTone, string> = {\n  primary: \"bg-primary\",\n  \"chart-1\": \"bg-chart-1\",\n  \"chart-2\": \"bg-chart-2\",\n  \"chart-3\": \"bg-chart-3\",\n  \"chart-4\": \"bg-chart-4\",\n  \"chart-5\": \"bg-chart-5\",\n  destructive: \"bg-destructive\",\n}\n\ntype PulseButtonProps = Omit<ButtonProps, \"asChild\"> & {\n  /** Color of the rings. */\n  tone?: PulseTone\n  /** How many rings leave the button, one after another. */\n  rings?: number\n  /** Seconds one ring takes to fade out. */\n  duration?: number\n  /** Turn the pulse off, for example once the person has acted. */\n  active?: boolean\n  /** Classes for the wrapper around the button and rings. */\n  wrapperClassName?: string\n}\n\nfunction PulseButton({ tone = \"primary\", rings = 2, duration = 2, active = true, shape, disabled, wrapperClassName, className, children, ...props }: PulseButtonProps) {\n  const reduce = useReducedMotion()\n  const [calm, setCalm] = React.useState(false)\n  const pulsing = active && !disabled && !calm\n  const radius = shape === \"pill\" ? \"rounded-full\" : \"rounded-md\"\n\n  return (\n    <span\n      data-slot=\"pulse-button\"\n      data-pulsing={pulsing || undefined}\n      onPointerEnter={() => setCalm(true)}\n      onPointerLeave={() => setCalm(false)}\n      onFocusCapture={() => setCalm(true)}\n      onBlurCapture={() => setCalm(false)}\n      className={cn(\"relative inline-flex\", wrapperClassName)}\n    >\n      {active && !disabled &&\n        Array.from({ length: rings }, (_, i) => (\n          <motion.span\n            key={i}\n            aria-hidden=\"true\"\n            className={cn(\"pointer-events-none absolute inset-0 -z-10\", radius, RING[tone])}\n            initial={false}\n            animate={reduce ? { scale: 1.12, opacity: 0.18 } : pulsing ? { scale: [1, 1.5], opacity: [0.35, 0] } : { scale: 1, opacity: 0 }}\n            transition={reduce ? { duration: 0 } : pulsing ? { duration, delay: (i * duration) / rings, repeat: Infinity, ease: \"easeOut\" } : { duration: 0.2 }}\n          />\n        ))}\n      <Button shape={shape} disabled={disabled} className={cn(\"relative z-0\", className)} {...props}>\n        {children}\n      </Button>\n    </span>\n  )\n}\n\nexport { PulseButton, type PulseButtonProps, type PulseTone }\n",
      "type": "registry:ui",
      "target": "@components/ballmac/pulse-button.tsx"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "button",
      "pulse",
      "attention",
      "cta",
      "notification"
    ],
    "version": "1.0.0",
    "updated": "2026-10-01",
    "ai": {
      "summary": "<PulseButton tone rings duration active>Label</PulseButton>. Rings stop on hover and focus, and when active is false or the button is disabled.",
      "whenToUse": [
        "Onboarding steps and 'try it now' prompts",
        "Live or record buttons"
      ],
      "whenNotToUse": [
        "More than one per view",
        "Anything permanent: attention fades if it never stops"
      ],
      "composesWith": [
        "button",
        "shiny-button",
        "status-dot"
      ],
      "a11y": [
        {
          "keys": "Enter / Space",
          "action": "Activates like any button"
        },
        {
          "keys": "Screen readers",
          "action": "Rings are aria-hidden"
        },
        {
          "keys": "Reduced motion",
          "action": "A still faint ring replaces the pulse"
        }
      ],
      "customization": [
        "tone",
        "rings",
        "duration",
        "active"
      ]
    },
    "examples": [
      "pulse-button-demo",
      "pulse-button-tones"
    ],
    "url": "https://ui.ballmac.com/components/pulse-button"
  },
  "categories": [
    "motion"
  ],
  "type": "registry:ui"
}