{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "animated-tooltip",
  "title": "Animated Tooltip",
  "description": "A tooltip that springs in and tilts in 3D as the pointer moves across its trigger.",
  "dependencies": ["framer-motion"],
  "registryDependencies": ["@godui/godui-theme"],
  "files": [
    {
      "path": "packages/components/src/animated-tooltip/animated-tooltip.tsx",
      "content": "\"use client\";\n\nimport {\n  AnimatePresence,\n  motion,\n  useMotionValue,\n  useSpring,\n  useTransform,\n} from \"framer-motion\";\nimport * as React from \"react\";\n\nexport type AnimatedTooltipSide = \"top\" | \"bottom\";\n\nexport type AnimatedTooltipProps = Omit<\n  React.HTMLAttributes<HTMLSpanElement>,\n  \"content\"\n> & {\n  /** Tooltip content shown on hover / focus. */\n  content: React.ReactNode;\n  /** Which side of the trigger the tooltip appears on. */\n  side?: AnimatedTooltipSide;\n  /** The trigger element the tooltip is attached to. */\n  children: React.ReactNode;\n};\n\nconst SPRING = { stiffness: 170, damping: 12, mass: 0.1 } as const;\n\nconst PANEL_BASE =\n  \"pointer-events-none absolute left-1/2 z-popover flex max-w-[16rem] -translate-x-1/2 flex-col items-center rounded-lg bg-foreground px-3 py-1.5 text-center text-xs font-medium text-background shadow-lg [transform-style:preserve-3d]\";\n\nconst AnimatedTooltip = React.forwardRef<HTMLSpanElement, AnimatedTooltipProps>(\n  ({ content, side = \"top\", className, children, ...props }, ref) => {\n    const [open, setOpen] = React.useState(false);\n\n    const x = useMotionValue(0);\n    const rotate = useSpring(useTransform(x, [-60, 60], [-14, 14]), SPRING);\n    const translateX = useSpring(useTransform(x, [-60, 60], [-12, 12]), SPRING);\n\n    const handleMouseMove = (e: React.MouseEvent<HTMLSpanElement>) => {\n      const rect = e.currentTarget.getBoundingClientRect();\n      x.set(e.clientX - rect.left - rect.width / 2);\n    };\n\n    const isTop = side === \"top\";\n\n    return (\n      // biome-ignore lint/a11y/noStaticElementInteractions: hover/focus only reveals a tooltip; the wrapped child stays the interactive element\n      <span\n        ref={ref}\n        data-slot=\"animated-tooltip\"\n        className={`relative inline-flex ${className ?? \"\"}`}\n        onMouseEnter={() => setOpen(true)}\n        onMouseLeave={() => setOpen(false)}\n        onFocus={() => setOpen(true)}\n        onBlur={() => setOpen(false)}\n        onMouseMove={handleMouseMove}\n        {...props}\n      >\n        <AnimatePresence mode=\"wait\">\n          {open ? (\n            <motion.span\n              role=\"tooltip\"\n              initial={{\n                opacity: 0,\n                y: isTop ? 8 : -8,\n                scale: 0.85,\n              }}\n              animate={{\n                opacity: 1,\n                y: 0,\n                scale: 1,\n                transition: {\n                  type: \"spring\",\n                  stiffness: 170,\n                  damping: 12,\n                  mass: 0.1,\n                },\n              }}\n              exit={{ opacity: 0, y: isTop ? 6 : -6, scale: 0.9 }}\n              style={{ rotate, x: translateX }}\n              className={`${PANEL_BASE} ${isTop ? \"bottom-[calc(100%+0.625rem)] origin-bottom\" : \"top-[calc(100%+0.625rem)] origin-top\"}`}\n            >\n              {content}\n              <span\n                aria-hidden\n                className={`absolute left-1/2 size-2 -translate-x-1/2 rotate-45 bg-foreground ${isTop ? \"top-[calc(100%-0.25rem)]\" : \"bottom-[calc(100%-0.25rem)]\"}`}\n              />\n            </motion.span>\n          ) : null}\n        </AnimatePresence>\n        {children}\n      </span>\n    );\n  },\n);\nAnimatedTooltip.displayName = \"AnimatedTooltip\";\n\nexport { AnimatedTooltip };\n",
      "type": "registry:ui",
      "target": "components/godui/animated-tooltip.tsx"
    }
  ],
  "type": "registry:ui"
}
