{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tooltip",
  "title": "Tooltip",
  "description": "Tooltip trigger and wrapper primitives for contextual help.",
  "dependencies": [
    "@radix-ui/react-tooltip"
  ],
  "registryDependencies": [
    "@circle-ui/utils"
  ],
  "files": [
    {
      "path": "registry/berlin/circle-ui/tooltip.tsx",
      "content": "// Generated from packages/ui/src/components/tooltip.tsx\n\"use client\";\n\nimport * as React from \"react\";\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\n\nimport { cn } from \"@/registry/berlin/lib/utils\";\n\nexport type TooltipSide = \"top\" | \"right\" | \"bottom\" | \"left\";\nexport type TooltipAlign = \"start\" | \"center\" | \"end\";\nexport type TooltipVariant = \"default\" | \"dark\";\n\nexport interface TooltipProps {\n  content?: React.ReactNode;\n  className?: string;\n  ariaLabel?: string;\n  side?: TooltipSide;\n  width?: number;\n  variant?: TooltipVariant;\n}\n\nexport interface TooltipWrapperProps {\n  content?: React.ReactNode;\n  children: React.ReactElement;\n  side?: TooltipSide;\n  align?: TooltipAlign;\n  width?: number;\n  variant?: TooltipVariant;\n  open?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  defaultOpen?: boolean;\n  collisionBoundary?: Element | Element[];\n  collisionPadding?: number;\n  dismissible?: boolean;\n  onDismiss?: () => void;\n  dismissOnScroll?: boolean;\n  dismissOnClickOutside?: boolean;\n}\n\nfunction InfoIcon({ className }: { className?: string }) {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className={className}\n      viewBox=\"0 0 12 12\"\n      fill=\"none\"\n    >\n      <path\n        d=\"M5.06 3.94a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0ZM11.06 6A5.06 5.06 0 1 1 .94 6a5.06 5.06 0 0 1 10.12 0ZM9.94 6A3.94 3.94 0 1 0 2.06 6a3.94 3.94 0 0 0 7.88 0ZM6.56 7.72V6.19a.94.94 0 0 0-.94-.94.56.56 0 0 0-.19 1.09v1.53a.94.94 0 0 0 .94.94.56.56 0 0 0 .19-1.09Z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  );\n}\n\nconst contentClassName = {\n  default:\n    \"relative box-border rounded-xl bg-card p-4 font-sans text-[12px] font-normal leading-[18px] text-muted-foreground shadow-[0_0_20px_rgba(0,0,0,0.08)]\",\n  dark: \"relative box-border max-w-[272px] rounded-lg bg-[#222222] p-4 font-sans text-[14px] font-medium leading-6 text-white shadow-[0_0_40px_rgba(0,0,0,0.08),0_0_40px_rgba(0,0,0,0.08)]\",\n} satisfies Record<TooltipVariant, string>;\n\nconst arrowClassName = {\n  default: \"fill-card drop-shadow-[0_0_20px_rgba(0,0,0,0.08)]\",\n  dark: \"fill-[#222222]\",\n} satisfies Record<TooltipVariant, string>;\n\nfunction TooltipContent({\n  content,\n  variant,\n  dismissible,\n  onDismiss,\n}: {\n  content: React.ReactNode;\n  variant: TooltipVariant;\n  dismissible?: boolean;\n  onDismiss?: () => void;\n}) {\n  return (\n    <div className={contentClassName[variant]}>\n      {dismissible && variant !== \"dark\" ? (\n        <button\n          type=\"button\"\n          className=\"absolute right-2 top-2 flex size-5 items-center justify-center border-0 bg-transparent p-0 text-current\"\n          aria-label=\"Close\"\n          onClick={onDismiss}\n        >\n          &times;\n        </button>\n      ) : null}\n      {content}\n    </div>\n  );\n}\n\nexport function Tooltip({\n  content,\n  className,\n  ariaLabel,\n  side = \"left\",\n  width = 204,\n  variant = \"default\",\n}: TooltipProps) {\n  const [open, setOpen] = React.useState(false);\n\n  if (!content) return null;\n\n  return (\n    <TooltipPrimitive.Provider delayDuration={0} skipDelayDuration={300}>\n      <TooltipPrimitive.Root open={open} onOpenChange={setOpen}>\n        <TooltipPrimitive.Trigger asChild>\n          <button\n            type=\"button\"\n            className={cn(\n              \"relative inline-flex cursor-pointer items-center justify-center p-1.5 text-[#0071e3]\",\n              className,\n            )}\n            aria-label={ariaLabel ?? \"Tooltip\"}\n            onClick={() => setOpen(true)}\n          >\n            <InfoIcon className=\"size-3\" />\n          </button>\n        </TooltipPrimitive.Trigger>\n        <TooltipPrimitive.Portal>\n          <TooltipPrimitive.Content\n            className=\"z-50 opacity-0 transition-opacity duration-200 data-[state=closed]:opacity-0 data-[state=delayed-open]:opacity-100 data-[state=instant-open]:opacity-100\"\n            side={side}\n            align=\"center\"\n            sideOffset={variant === \"dark\" ? -3 : -6}\n            style={{ width }}\n            forceMount\n          >\n            <TooltipContent content={content} variant={variant} />\n            <TooltipPrimitive.Arrow\n              className={arrowClassName[variant]}\n              width={variant === \"dark\" ? 20 : 12}\n              height={variant === \"dark\" ? 10 : 8}\n            />\n          </TooltipPrimitive.Content>\n        </TooltipPrimitive.Portal>\n      </TooltipPrimitive.Root>\n    </TooltipPrimitive.Provider>\n  );\n}\n\nexport const TooltipWrapper = React.memo(function TooltipWrapper({\n  content,\n  children,\n  side = \"left\",\n  align,\n  width = 204,\n  variant = \"default\",\n  open: controlledOpen,\n  onOpenChange,\n  defaultOpen = false,\n  collisionBoundary,\n  collisionPadding = 0,\n  dismissible,\n  onDismiss,\n  dismissOnScroll = false,\n  dismissOnClickOutside = false,\n}: TooltipWrapperProps) {\n  const [internalOpen, setInternalOpen] = React.useState(defaultOpen);\n  const isControlled = controlledOpen !== undefined;\n  const open = isControlled ? controlledOpen : internalOpen;\n\n  const handleOpenChange = React.useCallback(\n    (nextOpen: boolean) => {\n      if (!isControlled) setInternalOpen(nextOpen);\n      onOpenChange?.(nextOpen);\n    },\n    [isControlled, onOpenChange],\n  );\n\n  const handleDismiss = React.useCallback(() => {\n    onDismiss?.();\n    handleOpenChange(false);\n  }, [handleOpenChange, onDismiss]);\n\n  React.useEffect(() => {\n    if (!isControlled) setInternalOpen(defaultOpen);\n  }, [defaultOpen, isControlled]);\n\n  React.useEffect(() => {\n    if (!dismissOnScroll || !open) return;\n\n    window.addEventListener(\"scroll\", handleDismiss, true);\n    return () => window.removeEventListener(\"scroll\", handleDismiss, true);\n  }, [dismissOnScroll, handleDismiss, open]);\n\n  const shouldPreventDismissal =\n    isControlled && !dismissOnClickOutside && !dismissOnScroll;\n\n  if (!content) return children;\n\n  const childProps = children.props as {\n    onClick?: React.MouseEventHandler;\n  };\n\n  return (\n    <TooltipPrimitive.Provider\n      delayDuration={0}\n      skipDelayDuration={300}\n      disableHoverableContent={isControlled}\n    >\n      <TooltipPrimitive.Root\n        open={open}\n        onOpenChange={shouldPreventDismissal ? undefined : handleOpenChange}\n        defaultOpen={defaultOpen}\n      >\n        <TooltipPrimitive.Trigger asChild>\n          {React.cloneElement(children, {\n            onClick: (event: React.MouseEvent) => {\n              childProps.onClick?.(event);\n              if (!isControlled) setInternalOpen(true);\n            },\n          } as Partial<typeof childProps>)}\n        </TooltipPrimitive.Trigger>\n        <TooltipPrimitive.Portal>\n          <TooltipPrimitive.Content\n            className=\"z-50 opacity-0 transition-opacity duration-200 data-[state=closed]:opacity-0 data-[state=delayed-open]:opacity-100 data-[state=instant-open]:opacity-100\"\n            side={side}\n            align={align ?? (variant === \"dark\" ? \"end\" : \"center\")}\n            sideOffset={variant === \"dark\" ? -3 : -6}\n            collisionPadding={collisionPadding}\n            collisionBoundary={collisionBoundary}\n            style={{ width }}\n            forceMount\n            onPointerDownOutside={(event) => {\n              if (dismissOnClickOutside) {\n                handleDismiss();\n              } else if (shouldPreventDismissal) {\n                event.preventDefault();\n              }\n            }}\n            onEscapeKeyDown={(event) => {\n              if (shouldPreventDismissal) event.preventDefault();\n            }}\n          >\n            <TooltipContent\n              content={content}\n              variant={variant}\n              dismissible={dismissible}\n              onDismiss={handleDismiss}\n            />\n            <TooltipPrimitive.Arrow\n              className={arrowClassName[variant]}\n              width={variant === \"dark\" ? 20 : 12}\n              height={variant === \"dark\" ? 10 : 8}\n            />\n          </TooltipPrimitive.Content>\n        </TooltipPrimitive.Portal>\n      </TooltipPrimitive.Root>\n    </TooltipPrimitive.Provider>\n  );\n});\n\nTooltip.displayName = \"Tooltip\";\nTooltipWrapper.displayName = \"TooltipWrapper\";\n",
      "type": "registry:ui",
      "target": "src/components/circle/ui/tooltip.tsx"
    }
  ],
  "type": "registry:ui"
}