{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tooltip",
  "title": "Tooltip",
  "description": "A short plain-text label on hover or focus, after a delay.",
  "dependencies": [
    "@base-ui/react@^1.9.0"
  ],
  "registryDependencies": [
    "https://sproutboat.com/ikada/r/theme.json",
    "https://sproutboat.com/ikada/r/cn.json",
    "https://sproutboat.com/ikada/r/portal.json"
  ],
  "files": [
    {
      "path": "registry/ikada/ui/tooltip.tsx",
      "content": "\"use client\";\n\nimport { Tooltip as BaseTooltip } from \"@base-ui/react/tooltip\";\nimport { cloneElement, useId, useState } from \"react\";\nimport type { ComponentProps, ReactElement, ReactNode } from \"react\";\nimport { cn, floatingSurface } from \"@/components/ikada/lib/cn\";\nimport { usePortalContainer } from \"@/components/ikada/lib/portal\";\n\n/**\n * Warm skip-delay: the first tooltip waits 450ms; once one has closed, neighbours open\n * with no delay and no animation for 300ms, so sweeping a toolbar feels instant.\n */\nexport function TooltipProvider({ delay = 450, timeout = 300, ...props }: ComponentProps<typeof BaseTooltip.Provider>) {\n  return <BaseTooltip.Provider delay={delay} timeout={timeout} {...props} />;\n}\n\nexport interface TooltipProps {\n  /** Short plain text. Anything interactive belongs in a Popover. */\n  content: ReactNode;\n  /** The element that triggers the tooltip; it receives the trigger props. */\n  children: ReactElement;\n  side?: \"top\" | \"bottom\" | \"start\" | \"end\";\n  /** Milliseconds before it opens on hover. Default from TooltipProvider (450). */\n  delay?: number;\n  defaultOpen?: boolean;\n  className?: string;\n  ref?: ComponentProps<\"div\">[\"ref\"];\n}\n\n/** A short plain-text label on hover or focus, after a delay. Arrives on the snappy spring. */\nexport function Tooltip({ content, children, side = \"top\", delay, defaultOpen, className, ref }: TooltipProps) {\n  const container = usePortalContainer();\n  // Base UI shows the label but does not link it to the trigger, so a screen reader never hears it.\n  // While it is open, the trigger is described by it.\n  const id = useId();\n  const [open, setOpen] = useState(Boolean(defaultOpen));\n  return (\n    <BaseTooltip.Root defaultOpen={defaultOpen} onOpenChange={setOpen}>\n      <BaseTooltip.Trigger\n        render={cloneElement(children, { \"aria-describedby\": open ? id : undefined } as Record<string, unknown>)}\n        delay={delay}\n      />\n      <BaseTooltip.Portal container={container}>\n        <BaseTooltip.Positioner\n          side={side === \"start\" ? \"inline-start\" : side === \"end\" ? \"inline-end\" : side}\n          sideOffset={6}\n          collisionPadding={8}\n          className=\"z-(--sb-z-tooltip)\"\n        >\n          <BaseTooltip.Popup\n            data-slot=\"tooltip-content\"\n            ref={ref}\n            id={id}\n            role=\"tooltip\"\n            className={cn(\n              floatingSurface,\n              \"max-w-64 rounded-md px-2.5 py-1.5 text-sb-xs font-medium wrap-break-word\",\n              \"origin-(--transform-origin) [transition:opacity_var(--sb-duration-tooltip-out)_var(--ease-out),scale_var(--sb-duration-tooltip-out)_var(--ease-out)]\",\n              \"data-open:[transition:opacity_var(--sb-duration-tooltip-in)_var(--ease-out),scale_var(--sb-duration-spring-snappy)_var(--sb-spring-snappy)]\",\n              \"data-starting-style:scale-(--sb-scale-popup) data-starting-style:opacity-0\",\n              \"data-ending-style:scale-(--sb-scale-popup) data-ending-style:opacity-0\",\n              \"data-instant:transition-none\",\n              className,\n            )}\n          >\n            {content}\n          </BaseTooltip.Popup>\n        </BaseTooltip.Positioner>\n      </BaseTooltip.Portal>\n    </BaseTooltip.Root>\n  );\n}\n",
      "type": "registry:ui",
      "target": "@components/ikada/tooltip.tsx"
    }
  ],
  "docs": "Wrap your app (or the part that uses tooltips) in <TooltipProvider> once.",
  "categories": [
    "overlays"
  ],
  "type": "registry:ui"
}