{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "notra-tooltip",
  "title": "Tooltip",
  "description": "A Base UI tooltip with the Depth surface of the buttons that glides between neighbouring triggers.",
  "dependencies": [
    "@base-ui/react",
    "cn"
  ],
  "files": [
    {
      "path": "registry/notra/tooltip/components/tooltip.tsx",
      "content": "\"use client\";\n\nimport { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\";\nimport { cn } from \"cn\";\nimport {\n  createContext,\n  type Dispatch,\n  type ReactNode,\n  type SetStateAction,\n  use,\n  useLayoutEffect,\n  useMemo,\n  useState,\n} from \"react\";\n\ntype TooltipPlacement = Pick<\n  TooltipPrimitive.Positioner.Props,\n  \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n>;\n\ntype TooltipContentProps = TooltipPrimitive.Popup.Props & TooltipPlacement;\n\ntype SharedPopupProps = Omit<\n  TooltipPrimitive.Popup.Props,\n  \"children\" | \"className\"\n>;\n\ninterface SharedTooltipPayload extends TooltipPlacement {\n  children: ReactNode;\n  className?: string;\n  popupProps?: SharedPopupProps;\n}\n\ninterface SharedTooltipItem {\n  payload: SharedTooltipPayload | undefined;\n  setPayload: Dispatch<SetStateAction<SharedTooltipPayload | undefined>>;\n}\n\nconst tooltipContentClassName =\n  \"border-foreground/60 to-foreground text-background z-50 block w-fit max-w-xs origin-(--transform-origin) rounded-[0.625rem] border bg-linear-to-b from-[color-mix(in_oklab,var(--color-foreground),var(--color-background)_10%)] px-2.5 py-1 text-xs shadow-[inset_0_1px_0_rgba(255,255,255,0.22),0_1px_2px_rgba(0,0,0,0.16),0_6px_16px_-4px_rgba(0,0,0,0.24)] transition-[opacity,scale,translate] duration-150 ease-[cubic-bezier(0.23,1,0.32,1)] [corner-shape:squircle] has-[[data-slot=kbd]]:pr-1 data-ending-style:scale-[0.97] data-ending-style:opacity-0 data-ending-style:duration-100 data-starting-style:scale-[0.97] data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:-translate-y-0.5 data-[side=left]:data-starting-style:translate-x-0.5 data-[side=right]:data-starting-style:-translate-x-0.5 data-[side=top]:data-starting-style:translate-y-0.5 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm **:data-[slot=kbd]:align-middle **:data-[slot=kbd-group]:ms-1.5 **:data-[slot=kbd-group]:align-middle *:data-[slot=kbd]:ms-1.5 [--tooltip-arrow:var(--color-foreground)] **:[--color-border:color-mix(in_oklab,var(--color-background)_18%,transparent)] **:[--color-foreground:var(--color-background)] **:[--color-muted-foreground:color-mix(in_oklab,var(--color-background)_65%,transparent)] motion-reduce:transition-opacity\";\n\nconst TOOLTIP_ARROW_CLASS_NAME =\n  \"bg-(--tooltip-arrow) fill-(--tooltip-arrow) -z-10 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5\";\n\nconst SHARED_POSITIONER_CLASS_NAME =\n  \"h-(--positioner-height) w-(--positioner-width) transition-[top,left,right,bottom] duration-200 ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none\";\nconst SHARED_POPUP_CLASS_NAME =\n  \"h-(--popup-height) w-(--popup-width) max-w-none p-0 has-[[data-slot=kbd]]:pr-0 transition-[opacity,scale,translate,width,height] motion-reduce:transition-opacity\";\nconst SHARED_VIEWPORT_CLASS_NAME =\n  \"relative m-0! overflow-hidden rounded-[inherit] [&>[data-previous]]:hidden\";\nconst SHARED_CONTENT_CLASS_NAME =\n  \"w-max max-w-xs px-2.5 py-1 has-[[data-slot=kbd]]:pr-1\";\nconst SHARED_ARROW_CLASS_NAME =\n  \"transition-[left,top] duration-200 ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none\";\n\nconst SharedTooltipContext =\n  createContext<TooltipPrimitive.Handle<SharedTooltipPayload> | null>(null);\nconst SharedTooltipItemContext = createContext<SharedTooltipItem | null>(null);\n\nfunction TooltipFrame({\n  align = \"center\",\n  alignOffset = 0,\n  children,\n  className,\n  contentClassName,\n  shared = false,\n  side = \"top\",\n  sideOffset = 4,\n  ...props\n}: TooltipContentProps & { contentClassName?: string; shared?: boolean }) {\n  return (\n    <TooltipPrimitive.Portal>\n      <TooltipPrimitive.Positioner\n        align={align}\n        alignOffset={alignOffset}\n        side={side}\n        sideOffset={sideOffset}\n        className={cn(\n          \"isolate z-50 w-max\",\n          shared && SHARED_POSITIONER_CLASS_NAME\n        )}\n      >\n        <TooltipPrimitive.Popup\n          data-slot=\"tooltip-content\"\n          className={cn(\n            tooltipContentClassName,\n            className,\n            shared && contentClassName,\n            shared && SHARED_POPUP_CLASS_NAME\n          )}\n          {...props}\n        >\n          {shared ? (\n            <TooltipPrimitive.Viewport className={SHARED_VIEWPORT_CLASS_NAME}>\n              <div className={cn(SHARED_CONTENT_CLASS_NAME, contentClassName)}>\n                {children}\n              </div>\n            </TooltipPrimitive.Viewport>\n          ) : (\n            children\n          )}\n          <TooltipPrimitive.Arrow\n            className={cn(\n              TOOLTIP_ARROW_CLASS_NAME,\n              shared && SHARED_ARROW_CLASS_NAME\n            )}\n          />\n        </TooltipPrimitive.Popup>\n      </TooltipPrimitive.Positioner>\n    </TooltipPrimitive.Portal>\n  );\n}\n\nfunction TooltipProvider({\n  children,\n  delay = 0,\n  ...props\n}: TooltipPrimitive.Provider.Props) {\n  const [handle] = useState(() =>\n    TooltipPrimitive.createHandle<SharedTooltipPayload>()\n  );\n\n  return (\n    <TooltipPrimitive.Provider\n      data-slot=\"tooltip-provider\"\n      delay={delay}\n      {...props}\n    >\n      <SharedTooltipContext value={handle}>\n        {children}\n        <TooltipPrimitive.Root disableHoverablePopup handle={handle}>\n          {({ payload }) => {\n            const {\n              children: content,\n              className: contentClassName,\n              popupProps,\n              ...frameProps\n            } = (payload as SharedTooltipPayload | undefined) ?? {};\n            return (\n              <TooltipFrame\n                contentClassName={contentClassName}\n                shared\n                {...popupProps}\n                {...frameProps}\n              >\n                {content}\n              </TooltipFrame>\n            );\n          }}\n        </TooltipPrimitive.Root>\n      </SharedTooltipContext>\n    </TooltipPrimitive.Provider>\n  );\n}\n\nfunction Tooltip({ ...props }: TooltipPrimitive.Root.Props) {\n  const handle = use(SharedTooltipContext);\n  const [payload, setPayload] = useState<SharedTooltipPayload>();\n  const item = useMemo(() => ({ payload, setPayload }), [payload]);\n\n  if (handle) {\n    return (\n      <SharedTooltipItemContext value={item}>\n        {props.children as ReactNode}\n      </SharedTooltipItemContext>\n    );\n  }\n\n  return <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />;\n}\n\nfunction TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {\n  const handle = use(SharedTooltipContext);\n  const item = use(SharedTooltipItemContext);\n\n  if (handle && item) {\n    return (\n      <TooltipPrimitive.Trigger\n        data-slot=\"tooltip-trigger\"\n        disabled={!item.payload}\n        handle={handle}\n        payload={item.payload}\n        {...props}\n      />\n    );\n  }\n\n  return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />;\n}\n\nconst isSamePopupProps = (\n  a: SharedPopupProps | undefined,\n  b: SharedPopupProps | undefined\n) => {\n  const aKeys = Object.keys(a ?? {}) as (keyof SharedPopupProps)[];\n  const bKeys = Object.keys(b ?? {});\n  return (\n    aKeys.length === bKeys.length && aKeys.every((key) => a?.[key] === b?.[key])\n  );\n};\n\nconst isSamePayload = (\n  a: SharedTooltipPayload | undefined,\n  b: SharedTooltipPayload\n) =>\n  a !== undefined &&\n  a.align === b.align &&\n  a.alignOffset === b.alignOffset &&\n  a.children === b.children &&\n  a.className === b.className &&\n  a.side === b.side &&\n  a.sideOffset === b.sideOffset &&\n  isSamePopupProps(a.popupProps, b.popupProps);\n\nfunction SharedTooltipContent({\n  hidden,\n  setPayload,\n  ...payload\n}: SharedTooltipPayload & {\n  hidden?: boolean;\n  setPayload: SharedTooltipItem[\"setPayload\"];\n}) {\n  useLayoutEffect(() => {\n    if (hidden) {\n      setPayload(undefined);\n      return;\n    }\n    setPayload((current) =>\n      isSamePayload(current, payload) ? current : payload\n    );\n  });\n\n  useLayoutEffect(() => () => setPayload(undefined), [setPayload]);\n\n  return null;\n}\n\nfunction TooltipContent({\n  children,\n  className,\n  ...props\n}: TooltipContentProps) {\n  const item = use(SharedTooltipItemContext);\n\n  if (item) {\n    const { align, alignOffset, hidden, side, sideOffset, ...popupProps } =\n      props;\n    return (\n      <SharedTooltipContent\n        align={align}\n        alignOffset={alignOffset}\n        className={typeof className === \"string\" ? className : undefined}\n        hidden={hidden}\n        popupProps={popupProps}\n        setPayload={item.setPayload}\n        side={side}\n        sideOffset={sideOffset}\n      >\n        {children as ReactNode}\n      </SharedTooltipContent>\n    );\n  }\n\n  return (\n    <TooltipFrame className={className} {...props}>\n      {children}\n    </TooltipFrame>\n  );\n}\n\nexport {\n  Tooltip,\n  TooltipTrigger,\n  TooltipContent,\n  TooltipProvider,\n  tooltipContentClassName,\n};\n",
      "type": "registry:component",
      "target": "components/tooltip/components/tooltip.tsx"
    }
  ],
  "type": "registry:component"
}