diff --git a/src/ui.tsx b/src/ui.tsx index f04b582..0d4a0ec 100644 --- a/src/ui.tsx +++ b/src/ui.tsx @@ -277,22 +277,30 @@ function Plugin () { const [isMaxToggled, setIsMaxToggled] = useState(false) // Resize-handle visibility is state-driven (not CSS :hover/:has) for Figma webview - // reliability: show all handles when the window or any handle is hovered; hoveredHandle - // tracks the one under the cursor, rendered brighter. + // reliability. Handles appear only after the cursor has rested in the window for 500ms + // (so they don't flash while just passing through); the handle under the cursor is + // rendered a touch brighter than the others. const [rootHover, setRootHover] = useState(false) const [hoveredHandle, setHoveredHandle] = useState(null) - const handleVisible = rootHover || hoveredHandle !== null + const [handlesShown, setHandlesShown] = useState(false) + useEffect(function () { + if (rootHover) { + const t = setTimeout(function () { setHandlesShown(true) }, 500) + return function () { clearTimeout(t) } + } + setHandlesShown(false) + }, [rootHover]) function hitboxStyle (dir: string, pos: { [k: string]: number | string }) { const active = hoveredHandle === dir return { ...pos, position: 'fixed', zIndex: 3, - opacity: handleVisible ? 1 : 0, - background: active ? 'rgba(255,255,255,0.95)' : 'rgba(255,255,255,0.5)', - border: '1.5px solid ' + (active ? 'rgba(80,80,80,1)' : 'rgba(110,110,110,0.9)'), + opacity: handlesShown ? 1 : 0, + background: active ? 'rgba(255,255,255,0.6)' : 'rgba(255,255,255,0.3)', + border: '1px solid ' + (active ? 'rgba(90,90,90,0.85)' : 'rgba(120,120,120,0.6)'), borderRadius: 4, - transition: 'opacity 120ms ease, background 120ms ease, border-color 120ms ease' + transition: 'opacity 150ms ease, background 150ms ease, border-color 150ms ease' } as any } // "Maximized" flag drives the icon (expand/collapse). Real size after maximize is