{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "key-login-button",
  "title": "Key login button",
  "description": "Ledge’s green pill login button with a rotating key and rolling label on hover or keyboard focus.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/items/key-login-button/key-login-button.tsx",
      "content": "\"use client\";\n\nimport { useState, type MouseEventHandler } from \"react\";\nimport { motion, useReducedMotionConfig } from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\nexport type KeyLoginButtonProps = {\n  label?: string;\n  href?: string;\n  onClick?: MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>;\n  disabled?: boolean;\n  fullWidth?: boolean;\n  type?: \"button\" | \"submit\" | \"reset\";\n  className?: string;\n};\n\n/** Ledge's rotating key and rolling label, as a link or an action button. */\nexport function KeyLoginButton({ label = \"Log in\", href, onClick, disabled = false, fullWidth = false, type = \"button\", className }: KeyLoginButtonProps) {\n  const reducedMotion = useReducedMotionConfig();\n  const [active, setActive] = useState(false);\n  const moving = active && !disabled && !reducedMotion;\n  const content = <>\n    <motion.svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\" className=\"size-4 shrink-0\" animate={{ rotate: moving ? 45 : 0 }} transition={{ duration: reducedMotion ? 0 : 0.3, ease: \"easeOut\" }}>\n      <circle cx=\"7\" cy=\"17\" r=\"5\" />\n      <line x1=\"10.5\" y1=\"13.5\" x2=\"21\" y2=\"3\" />\n      <line x1=\"15\" y1=\"9\" x2=\"17.5\" y2=\"11.5\" />\n      <line x1=\"18\" y1=\"6\" x2=\"20.5\" y2=\"8.5\" />\n    </motion.svg>\n    <span className=\"relative block overflow-hidden\">\n      <motion.span className=\"block\" animate={{ y: moving ? \"-100%\" : \"0%\" }} transition={{ duration: reducedMotion ? 0 : 0.3, ease: \"easeOut\" }}>{label}</motion.span>\n      <motion.span aria-hidden=\"true\" className=\"absolute inset-0 block\" initial={{ y: \"100%\" }} animate={{ y: moving ? \"0%\" : \"100%\" }} transition={{ duration: reducedMotion ? 0 : 0.3, ease: \"easeOut\" }}>{label}</motion.span>\n    </span>\n  </>;\n  const classes = cn(\"inline-flex min-h-11 cursor-pointer items-center justify-center gap-2 rounded-full bg-primary px-6 py-2.5 font-body text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-lead motion-reduce:transition-none\", fullWidth && \"w-full\", disabled && \"pointer-events-none opacity-50\", className);\n  const events = {\n    onPointerEnter: () => setActive(true),\n    onPointerLeave: () => setActive(false),\n    onFocus: () => setActive(true),\n    onBlur: () => setActive(false),\n  };\n  return href\n    ? <a {...events} href={disabled ? undefined : href} aria-disabled={disabled || undefined} tabIndex={disabled ? -1 : undefined} onClick={disabled ? (event) => event.preventDefault() : onClick} className={classes}>{content}</a>\n    : <button {...events} type={type} disabled={disabled} onClick={onClick} className={classes}>{content}</button>;\n}\n",
      "type": "registry:ui"
    }
  ],
  "meta": {
    "kind": "primitive",
    "whenToUse": "Use as an entry action or login link. Supply href for navigation, or onClick / type=\"submit\" for an action.",
    "origin": {
      "project": "Ledge",
      "path": "src/components/landing/header.tsx"
    },
    "credits": []
  },
  "type": "registry:ui"
}
