{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "button",
  "type": "registry:ui",
  "dependencies": [
    "class-variance-authority",
    "@radix-ui/react-slot"
  ],
  "registryDependencies": [
    "https://ui.getlyse.com/r/lyse-tokens.json"
  ],
  "files": [
    {
      "path": "registry/new-york/ui/button/button.tsx",
      "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport \"./button.css\"\n\nconst buttonVariants = cva(\n  \"relative inline-flex items-center justify-center overflow-hidden whitespace-nowrap font-accent cursor-pointer transition-colors [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n  {\n    variants: {\n      variant: {\n        primary: \"btn-primary\",\n        secondary: \"btn-secondary\",\n        terciary: \"btn-terciary\",\n        destructive: \"btn-destructive\",\n      },\n      size: {\n        xs: \"h-[var(--layout-size-md)] gap-[var(--layout-gap-xs)] px-[var(--layout-padding-xs)] rounded-[var(--layout-radius-lg)] text-content-caption [&_svg]:size-3.5\",\n        sm: \"h-[var(--layout-size-lg)] gap-[var(--layout-gap-sm)] px-[var(--layout-padding-md)] rounded-[var(--layout-radius-lg)] text-content-note [&_svg]:h-[var(--layout-size-xs)] [&_svg]:w-[var(--layout-size-xs)]\",\n        md: \"h-[var(--layout-size-xl)] gap-[var(--layout-gap-sm)] px-[var(--layout-padding-lg)] rounded-[var(--layout-radius-lg)] text-content-note [&_svg]:h-[var(--layout-size-xs)] [&_svg]:w-[var(--layout-size-xs)]\",\n        lg: \"h-[var(--layout-size-2xl)] gap-[var(--layout-gap-sm)] px-[var(--layout-padding-xl)] rounded-[var(--layout-radius-xl)] text-content-body [&_svg]:h-[var(--layout-size-sm)] [&_svg]:w-[var(--layout-size-sm)]\",\n      },\n    },\n    defaultVariants: {\n      variant: \"primary\",\n      size: \"md\",\n    },\n  }\n)\n\nfunction Button({\n  className,\n  variant,\n  size,\n  isIconOnly = false,\n  asChild = false,\n  onPointerDown,\n  ...props\n}: React.ComponentProps<\"button\"> &\n  VariantProps<typeof buttonVariants> & {\n    asChild?: boolean\n    isIconOnly?: boolean\n  }) {\n  const Comp = asChild ? Slot : \"button\"\n\n  const handlePointerDown = React.useCallback(\n    (e: React.PointerEvent<HTMLButtonElement>) => {\n      onPointerDown?.(e)\n      const btn = e.currentTarget\n      const rect = btn.getBoundingClientRect()\n      const diameter = Math.sqrt(rect.width ** 2 + rect.height ** 2) * 2\n      const ripple = document.createElement(\"span\")\n      ripple.className = \"absolute rounded-full bg-current pointer-events-none animate-ripple motion-reduce:hidden\"\n      ripple.style.width = `${diameter}px`\n      ripple.style.height = `${diameter}px`\n      ripple.style.left = `${e.clientX - rect.left - diameter / 2}px`\n      ripple.style.top = `${e.clientY - rect.top - diameter / 2}px`\n      btn.appendChild(ripple)\n      ripple.addEventListener(\"animationend\", () => ripple.remove())\n    },\n    [onPointerDown]\n  )\n\n  return (\n    <Comp\n      data-slot=\"button\"\n      className={cn(\n        buttonVariants({ variant, size, className }),\n        isIconOnly && \"aspect-square px-0 gap-0\"\n      )}\n      onPointerDown={handlePointerDown}\n      {...props}\n    />\n  )\n}\n\nexport { Button, buttonVariants }\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/new-york/ui/button/button.css",
      "content": "/* ================================================================\n * BUTTON — Variant & State Styles\n * Structure (flex, height, gap, radius) lives in button.tsx via cva.\n * Theming (colors, borders, states) lives here via tokens.\n * ================================================================ */\n\n/* --------------------------------\n * Variants\n * -------------------------------- */\n\n/* Primary — Neutral strong */\n.btn-primary {\n  background: var(--background-neutral-strong-default);\n  color: var(--text-inverse);\n}\n.btn-primary:hover {\n  background: var(--background-neutral-strong-hover);\n}\n.btn-primary:active {\n  background: var(--background-neutral-strong-pressed);\n}\n.btn-primary:disabled {\n  background: var(--background-disabled);\n  color: var(--text-disabled);\n}\n\n/* Secondary — Faint + border */\n.btn-secondary {\n  background: var(--background-neutral-faint-default);\n  color: var(--text-base-strong);\n  border: var(--layout-border-thin) solid var(--border-default);\n}\n.btn-secondary:hover {\n  background: var(--background-neutral-faint-hover);\n}\n.btn-secondary:active {\n  background: var(--background-neutral-faint-pressed);\n}\n.btn-secondary:disabled {\n  background: var(--background-disabled);\n  color: var(--text-disabled);\n  border-color: var(--border-disabled);\n}\n\n/* Terciary — Ghost */\n.btn-terciary {\n  color: var(--text-base-strong);\n}\n.btn-terciary:hover {\n  background: var(--background-neutral-faint-hover);\n}\n.btn-terciary:active {\n  background: var(--background-neutral-faint-pressed);\n}\n.btn-terciary:disabled {\n  color: var(--text-disabled);\n}\n\n/* Destructive — Ghost danger */\n.btn-destructive {\n  color: var(--text-danger-moderate);\n}\n.btn-destructive:hover {\n  background: var(--background-danger-faint-hover);\n  color: var(--text-danger-moderate);\n}\n.btn-destructive:active {\n  background: var(--background-danger-faint-pressed);\n}\n.btn-destructive:disabled {\n  color: var(--text-disabled);\n}\n\n/* --------------------------------\n * Focus ring (all variants)\n * -------------------------------- */\n.btn-primary:focus-visible,\n.btn-secondary:focus-visible,\n.btn-terciary:focus-visible,\n.btn-destructive:focus-visible {\n  outline: none;\n  box-shadow: 0 0 0 2px var(--background-base), 0 0 0 4px var(--border-selected);\n}\n\n/* --------------------------------\n * Disabled (all variants)\n * -------------------------------- */\n.btn-primary:disabled,\n.btn-secondary:disabled,\n.btn-terciary:disabled,\n.btn-destructive:disabled {\n  pointer-events: none;\n}",
      "type": "registry:ui"
    }
  ]
}