{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "buttons-3d",
  "title": "3D buttons",
  "description": "Styled buttons: the 3D set. 5 decorative buttons variations (PushButton, TiltButton, LayeredButton, EmbossButton, LiftButton) on the ai2 token system, powered by framer-motion, reduced-motion aware and sized sm to xl. Part of the free styled layer.",
  "dependencies": [
    "motion@^12.42.2"
  ],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/buttons-3d.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { motion, useReducedMotion, type HTMLMotionProps } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* 3D button family: 5 variations on depth and press. All are sized, use framer-motion, take colour ONLY from semantic tokens and are reduced-motion safe. The shadows derive from tokens through color-mix (a black/white mix for the shadow, not a colour). */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nconst sizes: Record<StyledSize, string> = {\n  sm: \"h-8 gap-1.5 rounded-md px-3 text-sm\",\n  md: \"h-9 gap-2 rounded-lg px-4 text-sm\",\n  lg: \"h-10 gap-2 rounded-lg px-5 text-sm\",\n  xl: \"h-12 gap-2.5 rounded-xl px-6 text-base\",\n}\n\nconst base =\n  \"relative inline-flex shrink-0 select-none items-center justify-center font-medium whitespace-nowrap outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&_i]:text-base [&_i]:leading-none\"\n\ntype Props = HTMLMotionProps<\"button\"> & { size?: StyledSize }\n\n/* Push: a token-derived shadow under the body that presses down on click. */\nexport function PushButton({ className, size = \"md\", children, ...props }: Props) {\n  const reduce = useReducedMotion()\n  return (\n    <motion.button\n      data-slot=\"styled-button\"\n      whileHover={reduce ? undefined : { y: -2 }}\n      whileTap={reduce ? undefined : { y: 3 }}\n      transition={{ type: \"spring\", stiffness: 500, damping: 24 }}\n      className={cn(\n        base,\n        sizes[size],\n        \"bg-brand text-brand-foreground shadow-[0_4px_0_0_color-mix(in_oklab,var(--brand)_70%,black)]\",\n        className\n      )}\n      {...props}\n    >\n      {children}\n    </motion.button>\n  )\n}\n\n/* Tilt: a 3D perspective tilt at a fixed angle rather than towards the cursor. */\nexport function TiltButton({ className, size = \"md\", children, ...props }: Props) {\n  const reduce = useReducedMotion()\n  return (\n    <motion.button\n      data-slot=\"styled-button\"\n      style={{ transformPerspective: 600 }}\n      whileHover={reduce ? undefined : { rotateX: 18, rotateY: -12, scale: 1.04 }}\n      whileTap={reduce ? undefined : { scale: 0.97 }}\n      transition={{ type: \"spring\", stiffness: 300, damping: 18 }}\n      className={cn(base, sizes[size], \"bg-primary text-primary-foreground\", className)}\n      {...props}\n    >\n      {children}\n    </motion.button>\n  )\n}\n\n/* Layered: token yuzeylerden istiflenmis katmanli govde; basinca toplanir. */\nexport function LayeredButton({ className, size = \"md\", children, ...props }: Props) {\n  const reduce = useReducedMotion()\n  return (\n    <motion.button\n      data-slot=\"styled-button\"\n      whileHover={reduce ? undefined : { x: -1, y: -1 }}\n      whileTap={reduce ? undefined : { x: 4, y: 4 }}\n      transition={{ type: \"spring\", stiffness: 500, damping: 26 }}\n      className={cn(\n        base,\n        sizes[size],\n        \"border border-border bg-secondary text-secondary-foreground shadow-[3px_3px_0_0_var(--surface-3),6px_6px_0_0_var(--surface-2)]\",\n        className\n      )}\n      {...props}\n    >\n      {children}\n    </motion.button>\n  )\n}\n\n/* Emboss: token yuzeyde is golgelerle kabartma; basinca oyuk gorunur. */\nexport function EmbossButton({ className, size = \"md\", children, ...props }: Props) {\n  const reduce = useReducedMotion()\n  return (\n    <motion.button\n      data-slot=\"styled-button\"\n      whileTap={reduce ? undefined : { scale: 0.98 }}\n      transition={{ type: \"spring\", stiffness: 500, damping: 26 }}\n      className={cn(\n        base,\n        sizes[size],\n        \"bg-secondary text-secondary-foreground shadow-[inset_0_1px_0_0_color-mix(in_oklab,var(--secondary)_60%,white),inset_0_-2px_0_0_color-mix(in_oklab,var(--secondary)_70%,black)] active:shadow-[inset_0_2px_4px_0_color-mix(in_oklab,var(--secondary)_70%,black)]\",\n        className\n      )}\n      {...props}\n    >\n      {children}\n    </motion.button>\n  )\n}\n\n/* Lift: rises on hover and the shadow beneath grows (a floating-card feel). */\nexport function LiftButton({ className, size = \"md\", children, ...props }: Props) {\n  const reduce = useReducedMotion()\n  return (\n    <motion.button\n      data-slot=\"styled-button\"\n      whileHover={reduce ? undefined : { y: -4 }}\n      whileTap={reduce ? undefined : { y: -1, scale: 0.98 }}\n      transition={{ type: \"spring\", stiffness: 350, damping: 20 }}\n      className={cn(\n        base,\n        sizes[size],\n        \"bg-primary text-primary-foreground shadow-md transition-shadow duration-(--motion-base) hover:shadow-xl\",\n        className\n      )}\n      {...props}\n    >\n      {children}\n    </motion.button>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/buttons-3d.tsx"
    }
  ],
  "categories": [
    "styled",
    "buttons"
  ],
  "type": "registry:component"
}