{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tooltip",
  "type": "registry:component",
  "title": "Tooltip",
  "description": "A short hint about a control while it is hovered or focused: a pill, a card, its keys or a status.",
  "dependencies": [
    "@base-ui/react",
    "tailwind-variants"
  ],
  "registryDependencies": [],
  "cssVars": {
    "light": {
      "success": "oklch(0.696 0.17 162.48)",
      "warning": "oklch(0.769 0.188 70.08)",
      "info": "oklch(0.623 0.214 259.815)"
    },
    "dark": {
      "success": "oklch(0.696 0.17 162.48)",
      "warning": "oklch(0.769 0.188 70.08)",
      "info": "oklch(0.623 0.214 259.815)"
    }
  },
  "files": [
    {
      "path": "components/panelui/tooltip.tsx",
      "type": "registry:component",
      "target": "@components/panelui/tooltip.tsx",
      "content": "'use client';\n\n/**\n * Tooltip — a short hint about a control, shown while it is hovered or focused.\n *\n * ```tsx\n * <Tooltip.Provider>\n *   <Tooltip>\n *     <Tooltip.Trigger render={<Button variant=\"ghost\" size=\"icon\" aria-label=\"Bold\" />}>\n *       <BoldIcon />\n *     </Tooltip.Trigger>\n *     <Tooltip.Content variant=\"shortcut\">\n *       Bold <Tooltip.Shortcut keys={['⌘', 'B']} />\n *     </Tooltip.Content>\n *   </Tooltip>\n * </Tooltip.Provider>\n * ```\n *\n * ## Five looks\n *\n * `solid` is a small pill in the inverse of the page, for one or two words.\n * `outline` is the popover surface with a hairline edge, for a hint that\n * should sit quietly beside the content. `shortcut` sets the name and its\n * keys side by side on a frosted chip. `rich` is a small card with a title\n * and a line or two under it, for explaining what a control does. `tone`\n * tints it in a status colour with a dot, for a hint that is a warning or a\n * confirmation.\n *\n * ## Timing\n *\n * The first tooltip waits half a second, so passing over a toolbar does not\n * flash one at every button. Once one is open, moving to the next opens it at\n * once and without animating, so reading along a row of icons is quick. That\n * hand-off is the provider's job: put one `Tooltip.Provider` round a group of\n * tooltips, or round the app.\n *\n * ## Motion\n *\n * It grows out of its trigger, from 97% and transparent, in 125ms. Growing\n * from the trigger's side rather than its own centre keeps it attached to the\n * thing it is about.\n *\n * ## Not for anything that matters\n *\n * A tooltip cannot be reached on a touch screen and is easy to miss. Put\n * nothing in it that a person needs in order to use the page, and nothing\n * that can be pressed: for that, use a popover.\n */\nimport { Tooltip as BaseTooltip } from '@base-ui/react/tooltip';\nimport { createContext, useContext, type ComponentProps, type ReactNode } from 'react';\nimport { tv } from 'tailwind-variants';\n\nexport type TooltipVariant = 'solid' | 'outline' | 'shortcut' | 'rich' | 'tone';\nexport type TooltipTone = 'info' | 'success' | 'warning' | 'destructive';\n\nconst tooltipVariants = tv({\n  slots: {\n    positioner: 'z-50',\n    popup: [\n      'relative origin-(--transform-origin) outline-none',\n      'transition-[opacity,scale] duration-[125ms] ease-[cubic-bezier(0.23,1,0.32,1)]',\n      'data-starting-style:scale-[0.97] data-starting-style:opacity-0 data-ending-style:scale-[0.97] data-ending-style:opacity-0',\n      // A second tooltip opened while one is showing appears in place.\n      'data-instant:transition-none motion-reduce:transition-none',\n    ],\n    // A square turned 45° and half hidden, so it can carry the popup's border.\n    arrow: [\n      'relative block h-1.5 w-3 overflow-clip',\n      'data-[side=top]:-bottom-1.5 data-[side=top]:rotate-180',\n      'data-[side=bottom]:-top-1.5',\n      'data-[side=left]:-right-[9px] data-[side=left]:rotate-90',\n      'data-[side=right]:-left-[9px] data-[side=right]:-rotate-90',\n      \"before:absolute before:bottom-0 before:left-1/2 before:size-[calc(6px*sqrt(2))] before:content-['']\",\n      'before:[transform:translate(-50%,50%)_rotate(45deg)]',\n    ],\n    title: 'font-medium',\n    description: '',\n    shortcut: 'ms-auto flex items-center gap-0.5 ps-2',\n    key: 'inline-flex h-5 min-w-5 items-center justify-center rounded-[5px] px-1 font-sans text-[0.6875rem] leading-none font-medium',\n    dot: 'size-1.5 shrink-0 rounded-full bg-(--tooltip-tone)',\n  },\n  variants: {\n    variant: {\n      solid: {\n        popup: 'max-w-64 rounded-md bg-foreground px-2 py-1 text-xs leading-4 font-medium text-background',\n        arrow: 'before:bg-foreground',\n        description: 'opacity-70',\n        key: 'bg-background/15 text-background',\n      },\n      outline: {\n        popup:\n          'max-w-64 rounded-lg border bg-popover px-2.5 py-1.5 text-xs leading-4 text-popover-foreground shadow-md shadow-black/5',\n        arrow: 'before:border before:bg-popover',\n        description: 'text-muted-foreground',\n        key: 'border bg-muted text-muted-foreground',\n      },\n      shortcut: {\n        popup: [\n          'flex max-w-72 items-center gap-1 rounded-lg border bg-popover/85 py-1 ps-2.5 pe-1 text-xs leading-5 text-popover-foreground',\n          'shadow-lg shadow-black/10 backdrop-blur-md backdrop-saturate-150',\n        ],\n        arrow: 'hidden',\n        description: 'text-muted-foreground',\n        key: 'border border-b-2 bg-background text-foreground',\n      },\n      rich: {\n        popup:\n          'flex w-64 flex-col gap-1 rounded-xl border bg-popover p-3 text-[0.8125rem] leading-5 text-popover-foreground shadow-lg shadow-black/10',\n        arrow: 'before:border before:bg-popover',\n        title: 'text-sm text-foreground',\n        description: 'text-muted-foreground',\n        key: 'border bg-muted text-muted-foreground',\n      },\n      tone: {\n        popup: [\n          'flex max-w-72 items-center gap-2 rounded-lg border px-2.5 py-1.5 text-xs leading-4 font-medium',\n          'border-[color-mix(in_oklab,var(--tooltip-tone)_28%,var(--background))]',\n          'bg-[color-mix(in_oklab,var(--tooltip-tone)_10%,var(--background))] dark:bg-[color-mix(in_oklab,var(--tooltip-tone)_18%,var(--background))]',\n          'text-[color-mix(in_oklab,var(--tooltip-tone),var(--foreground)_35%)] shadow-md shadow-black/5',\n        ],\n        arrow: [\n          'before:border before:border-[color-mix(in_oklab,var(--tooltip-tone)_28%,var(--background))]',\n          'before:bg-[color-mix(in_oklab,var(--tooltip-tone)_10%,var(--background))] dark:before:bg-[color-mix(in_oklab,var(--tooltip-tone)_18%,var(--background))]',\n        ],\n        description: 'font-normal opacity-80',\n        key: 'bg-background/60',\n      },\n    },\n    tone: {\n      info: { popup: '[--tooltip-tone:var(--info)]' },\n      success: { popup: '[--tooltip-tone:var(--success)]' },\n      warning: { popup: '[--tooltip-tone:var(--warning)]' },\n      destructive: { popup: '[--tooltip-tone:var(--destructive)]' },\n    },\n  },\n  defaultVariants: { variant: 'solid', tone: 'info' },\n});\n\nconst TooltipLook = createContext<TooltipVariant>('solid');\n\nexport interface TooltipProviderProps extends BaseTooltip.Provider.Props {}\n\n/**\n * Shares the timing between the tooltips inside it, so that once one is open\n * the next opens at once. Default `delay` 500ms, `closeDelay` 0.\n */\nfunction TooltipProvider({ delay = 500, closeDelay = 0, ...props }: TooltipProviderProps) {\n  return <BaseTooltip.Provider delay={delay} closeDelay={closeDelay} {...props} />;\n}\nTooltipProvider.displayName = 'Tooltip.Provider';\n\nexport type TooltipProps = BaseTooltip.Root.Props;\n\n/** One tooltip: its trigger and its content. Takes `open`/`onOpenChange`, `defaultOpen` and `trackCursorAxis`. */\nfunction TooltipRoot(props: TooltipProps) {\n  return <BaseTooltip.Root {...props} />;\n}\nTooltipRoot.displayName = 'Tooltip';\n\nexport interface TooltipTriggerProps extends BaseTooltip.Trigger.Props {\n  className?: string;\n}\n\n/** What the tooltip is about. A button unless `render` draws it as something else. */\nfunction TooltipTrigger(props: TooltipTriggerProps) {\n  return <BaseTooltip.Trigger data-slot=\"tooltip-trigger\" {...props} />;\n}\nTooltipTrigger.displayName = 'Tooltip.Trigger';\n\nexport interface TooltipContentProps extends Omit<BaseTooltip.Popup.Props, 'children'> {\n  /** Its look: `solid`, `outline`, `shortcut`, `rich` or `tone`. Default `solid`. */\n  variant?: TooltipVariant;\n  /** The status colour of a `tone` tooltip. Default `info`. */\n  tone?: TooltipTone;\n  /** Which side of the trigger it opens on. It moves to the other side where there is no room. Default `top`. */\n  side?: BaseTooltip.Positioner.Props['side'];\n  /** How it lines up with the trigger along that side. Default `center`. */\n  align?: BaseTooltip.Positioner.Props['align'];\n  /** The gap between the trigger and the tooltip, in pixels. Default `8`, or `6` without an arrow. */\n  sideOffset?: number;\n  /** Whether a small arrow points at the trigger. The `shortcut` look never has one. Default `true`. */\n  arrow?: boolean;\n  /** Where in the document it is put. Default `document.body`. */\n  container?: BaseTooltip.Portal.Props['container'];\n  className?: string;\n  children?: ReactNode;\n}\n\n/** The hint itself, in a layer over the page. */\nfunction TooltipContent({\n  variant = 'solid',\n  tone,\n  side = 'top',\n  align = 'center',\n  sideOffset,\n  arrow = true,\n  container,\n  className,\n  children,\n  ...props\n}: TooltipContentProps) {\n  const slots = tooltipVariants({ variant, tone });\n  const pointed = arrow && variant !== 'shortcut';\n  return (\n    <BaseTooltip.Portal container={container}>\n      <BaseTooltip.Positioner\n        side={side}\n        align={align}\n        sideOffset={sideOffset ?? (pointed ? 8 : 6)}\n        collisionPadding={8}\n        className={slots.positioner()}\n      >\n        <BaseTooltip.Popup\n          data-slot=\"tooltip-content\"\n          data-variant={variant}\n          className={slots.popup({ className })}\n          {...props}\n        >\n          {pointed ? <BaseTooltip.Arrow data-slot=\"tooltip-arrow\" className={slots.arrow()} /> : null}\n          {variant === 'tone' ? <span aria-hidden=\"true\" data-slot=\"tooltip-dot\" className={slots.dot()} /> : null}\n          <TooltipLook.Provider value={variant}>{children}</TooltipLook.Provider>\n        </BaseTooltip.Popup>\n      </BaseTooltip.Positioner>\n    </BaseTooltip.Portal>\n  );\n}\nTooltipContent.displayName = 'Tooltip.Content';\n\nexport interface TooltipTitleProps extends ComponentProps<'p'> {}\n\n/** The first line of a `rich` tooltip, in a heavier weight. */\nfunction TooltipTitle({ className, ...props }: TooltipTitleProps) {\n  const variant = useContext(TooltipLook);\n  return <p data-slot=\"tooltip-title\" className={tooltipVariants({ variant }).title({ className })} {...props} />;\n}\nTooltipTitle.displayName = 'Tooltip.Title';\n\nexport interface TooltipDescriptionProps extends ComponentProps<'p'> {}\n\n/** Quieter words under the title, or after the label. */\nfunction TooltipDescription({ className, ...props }: TooltipDescriptionProps) {\n  const variant = useContext(TooltipLook);\n  return (\n    <p data-slot=\"tooltip-description\" className={tooltipVariants({ variant }).description({ className })} {...props} />\n  );\n}\nTooltipDescription.displayName = 'Tooltip.Description';\n\nexport interface TooltipShortcutProps extends Omit<ComponentProps<'span'>, 'children'> {\n  /** The keys, each drawn as a key cap: `['⌘', 'K']`. */\n  keys: readonly string[];\n}\n\n/** The keys for the action, at the end of the line. It only shows them; handle the keys where the action lives. */\nfunction TooltipShortcut({ keys, className, ...props }: TooltipShortcutProps) {\n  const variant = useContext(TooltipLook);\n  const slots = tooltipVariants({ variant });\n  return (\n    <span data-slot=\"tooltip-shortcut\" className={slots.shortcut({ className })} {...props}>\n      {keys.map((key, index) => (\n        <kbd key={`${key}-${index}`} className={slots.key()}>\n          {key}\n        </kbd>\n      ))}\n    </span>\n  );\n}\nTooltipShortcut.displayName = 'Tooltip.Shortcut';\n\nexport const Tooltip = Object.assign(TooltipRoot, {\n  Provider: TooltipProvider,\n  Trigger: TooltipTrigger,\n  Content: TooltipContent,\n  Title: TooltipTitle,\n  Description: TooltipDescription,\n  Shortcut: TooltipShortcut,\n});\n\nexport { TooltipProvider, TooltipTrigger, TooltipContent, TooltipTitle, TooltipDescription, TooltipShortcut };\n"
    }
  ]
}
