Browse Source

comment tooltip z axis fixes

handoff-20260429-1057
Shrimbly 7 months ago
parent
commit
89649eb52d
  1. 3
      .claude/settings.local.json
  2. 35
      src/components/nodes/BaseNode.tsx

3
.claude/settings.local.json

@ -14,7 +14,8 @@
"WebSearch", "WebSearch",
"WebFetch(domain:ai.google.dev)", "WebFetch(domain:ai.google.dev)",
"Bash(grep:*)", "Bash(grep:*)",
"WebFetch(domain:www.cursor-ide.com)" "WebFetch(domain:www.cursor-ide.com)",
"Bash(git log:*)"
], ],
"deny": [], "deny": [],
"ask": [] "ask": []

35
src/components/nodes/BaseNode.tsx

@ -1,6 +1,7 @@
"use client"; "use client";
import { ReactNode, useCallback, useState, useEffect, useRef } from "react"; import { ReactNode, useCallback, useState, useEffect, useRef } from "react";
import { createPortal } from "react-dom";
import { NodeResizer, OnResize, useReactFlow } from "@xyflow/react"; import { NodeResizer, OnResize, useReactFlow } from "@xyflow/react";
import { useWorkflowStore } from "@/store/workflowStore"; import { useWorkflowStore } from "@/store/workflowStore";
@ -45,8 +46,10 @@ export function BaseNode({
const [isEditingComment, setIsEditingComment] = useState(false); const [isEditingComment, setIsEditingComment] = useState(false);
const [editCommentValue, setEditCommentValue] = useState(comment || ""); const [editCommentValue, setEditCommentValue] = useState(comment || "");
const [showCommentTooltip, setShowCommentTooltip] = useState(false); const [showCommentTooltip, setShowCommentTooltip] = useState(false);
const [tooltipPosition, setTooltipPosition] = useState<{ top: number; left: number } | null>(null);
const titleInputRef = useRef<HTMLInputElement>(null); const titleInputRef = useRef<HTMLInputElement>(null);
const commentPopoverRef = useRef<HTMLDivElement>(null); const commentPopoverRef = useRef<HTMLDivElement>(null);
const commentButtonRef = useRef<HTMLButtonElement>(null);
// Sync state with props // Sync state with props
useEffect(() => { useEffect(() => {
@ -69,6 +72,19 @@ export function BaseNode({
} }
}, [isEditingTitle]); }, [isEditingTitle]);
// Calculate tooltip position when showing
useEffect(() => {
if (showCommentTooltip && commentButtonRef.current) {
const rect = commentButtonRef.current.getBoundingClientRect();
setTooltipPosition({
top: rect.top - 8,
left: rect.right,
});
} else {
setTooltipPosition(null);
}
}, [showCommentTooltip]);
// Title handlers // Title handlers
const handleTitleSubmit = useCallback(() => { const handleTitleSubmit = useCallback(() => {
const trimmed = editTitleValue.trim(); const trimmed = editTitleValue.trim();
@ -198,6 +214,7 @@ export function BaseNode({
{/* Comment Icon */} {/* Comment Icon */}
<div className="relative ml-2 shrink-0" ref={commentPopoverRef}> <div className="relative ml-2 shrink-0" ref={commentPopoverRef}>
<button <button
ref={commentButtonRef}
onClick={() => setIsEditingComment(!isEditingComment)} onClick={() => setIsEditingComment(!isEditingComment)}
onMouseEnter={() => comment && setShowCommentTooltip(true)} onMouseEnter={() => comment && setShowCommentTooltip(true)}
onMouseLeave={() => setShowCommentTooltip(false)} onMouseLeave={() => setShowCommentTooltip(false)}
@ -219,16 +236,24 @@ export function BaseNode({
)} )}
</button> </button>
{/* Comment Tooltip on Hover */} {/* Comment Tooltip on Hover - rendered via portal to escape stacking context */}
{showCommentTooltip && comment && !isEditingComment && ( {showCommentTooltip && comment && !isEditingComment && tooltipPosition && createPortal(
<div className="absolute z-50 right-0 bottom-full mb-1 w-48 p-2 text-xs text-neutral-200 bg-neutral-900 border border-neutral-700 rounded shadow-lg whitespace-pre-wrap break-words"> <div
className="fixed z-[9999] w-48 p-2 text-xs text-neutral-200 bg-neutral-900 border border-neutral-700 rounded shadow-lg whitespace-pre-wrap break-words pointer-events-none"
style={{
top: tooltipPosition.top,
left: tooltipPosition.left,
transform: "translateY(-100%) translateX(-100%)",
}}
>
{comment} {comment}
</div> </div>,
document.body
)} )}
{/* Comment Edit Popover */} {/* Comment Edit Popover */}
{isEditingComment && ( {isEditingComment && (
<div className="absolute z-50 right-0 top-full mt-1 w-64 p-2 bg-neutral-800 border border-neutral-600 rounded shadow-lg"> <div className="absolute z-[60] right-0 top-full mt-1 w-64 p-2 bg-neutral-800 border border-neutral-600 rounded shadow-lg">
<textarea <textarea
value={editCommentValue} value={editCommentValue}
onChange={(e) => setEditCommentValue(e.target.value)} onChange={(e) => setEditCommentValue(e.target.value)}

Loading…
Cancel
Save