// ~/src/siteplane/components/tooltip/tooltip.tsx
"use client";
import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
import type React from "react";
import { SiteplaneUIPortalScope } from "../../system/provider/siteplane-ui-provider";
import { surfaceClassNames } from "../../system/styles/surface";
import { cn, type WithStringClassName } from "../../system/utils/cn";
import { slotClass } from "../../system/utils/slot-class";
export const TooltipCreateHandle: typeof TooltipPrimitive.createHandle =
TooltipPrimitive.createHandle;
export function TooltipProvider({
delay = 700,
timeout = 550,
...props
}: TooltipPrimitive.Provider.Props): React.ReactElement {
return (
);
}
export const Tooltip: typeof TooltipPrimitive.Root = TooltipPrimitive.Root;
/** How far the arrow reaches out of the popup: --sp-rw-space-1, in px. */
const TOOLTIP_ARROW_DEPTH = 4;
export function TooltipTrigger(
props: WithStringClassName,
): React.ReactElement {
return (
);
}
export type TooltipTone = "neutral" | "error";
/**
* @deprecated The earlier names of the two tones: `default` is `neutral` and
* `destructive` is `error`.
*/
export type TooltipDeprecatedTone = "default" | "destructive";
export function TooltipPopup({
className,
align = "center",
sideOffset = 4,
side = "top",
anchor,
disableAnchorTracking,
arrow = false,
children,
interactive = true,
portalProps,
tone = "neutral",
variant = "default",
...props
}: WithStringClassName & {
align?: TooltipPrimitive.Positioner.Props["align"];
side?: TooltipPrimitive.Positioner.Props["side"];
sideOffset?: TooltipPrimitive.Positioner.Props["sideOffset"];
anchor?: TooltipPrimitive.Positioner.Props["anchor"];
/**
* Stops the popup from watching its anchor and itself for changes of size
* and place. For an anchor that its owner moves and hands over again at
* every frame, such as the card of a chart that trails its item, which
* would otherwise set the watching up anew at every frame.
*/
disableAnchorTracking?: TooltipPrimitive.Positioner.Props["disableAnchorTracking"];
/**
* Points an arrow at the anchor. The arrow reaches into the side offset,
* so the gap between the arrow's tip and the anchor stays `sideOffset`.
*/
arrow?: boolean;
/**
* `false` lets the pointer pass through the popup, for a bubble that only
* reports, such as a field's error.
*/
interactive?: boolean;
portalProps?: WithStringClassName;
/**
* `error` fills the popup with the solid destructive colour of the Badge's
* destructive variant, for an error; `neutral`, the default, keeps the
* secondary surface. `default` and `destructive` are the deprecated earlier
* names of `neutral` and `error`.
*/
tone?: TooltipTone | TooltipDeprecatedTone;
/**
* `glass` lays the shared glass surface over whatever sits behind the
* tooltip. `tone` applies to the default surface only.
*/
variant?: "default" | "glass";
}): React.ReactElement {
return (
{arrow && (
)}
{/* The cross-fade of the current and the previous content, with
its width and its reduced-motion rules, is the viewport rule
it shares with Popover in design-rework.css. */}
{children}
);
}
// TooltipContent is the shadcn name of TooltipPopup.
export { TooltipPrimitive, TooltipPopup as TooltipContent };
// ~/src/siteplane/components/tooltip/index.ts
export * from "./tooltip";