diff --git a/src/frontend/src/components/ui/tooltip.tsx b/src/frontend/src/components/ui/tooltip.tsx
index dad190e2a9..59974d47b0 100644
--- a/src/frontend/src/components/ui/tooltip.tsx
+++ b/src/frontend/src/components/ui/tooltip.tsx
@@ -10,9 +10,65 @@ const TooltipProvider = ({
);
-const Tooltip = TooltipPrimitive.Root;
+type TooltipControl = {
+ open: boolean;
+ setOpen: (next: boolean) => void;
+};
+
+const TooltipContext = React.createContext(null);
+
+/**
+ * Radix Tooltip is hover/focus driven, so coarse pointers (finger / stylus tap)
+ * never see it on iPad/iPhone. Wrap Root with a small controlled-state shim and
+ * let the Trigger toggle it on touch / pen pointerdown without affecting mouse.
+ */
+const Tooltip = ({
+ open: openProp,
+ defaultOpen,
+ onOpenChange,
+ ...props
+}: React.ComponentPropsWithoutRef) => {
+ const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false);
+ const isControlled = openProp !== undefined;
+ const open = isControlled ? openProp : internalOpen;
+
+ const setOpen = React.useCallback(
+ (next: boolean) => {
+ if (!isControlled) {
+ setInternalOpen(next);
+ }
+ onOpenChange?.(next);
+ },
+ [isControlled, onOpenChange],
+ );
-const TooltipTrigger = TooltipPrimitive.Trigger;
+ return (
+
+
+
+ );
+};
+
+const TooltipTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>((props, ref) => {
+ const ctx = React.useContext(TooltipContext);
+ return (
+ {
+ props.onPointerDown?.(e);
+ if (!ctx) return;
+ if (e.pointerType === "touch" || e.pointerType === "pen") {
+ ctx.setOpen(!ctx.open);
+ }
+ }}
+ />
+ );
+});
+TooltipTrigger.displayName = TooltipPrimitive.Trigger.displayName;
const hasNoSpaces = (str: string): boolean => {
const trimmed = str.trim();