mirror of
https://github.com/zvx-echo6/navi.git
synced 2026-05-20 14:44:51 +02:00
fix(radial): use backdrop element for click-outside dismiss
Replace unreliable window event listener with transparent full-screen backdrop element. Clicking anywhere outside the radial menu now properly dismisses it. Also handles right-click on backdrop for dismiss. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
2e975ea59e
commit
741d760760
1 changed files with 140 additions and 130 deletions
|
|
@ -44,24 +44,6 @@ export default function RadialMenu({
|
|||
return () => window.removeEventListener('keydown', handleKey)
|
||||
}, [open, onDismiss])
|
||||
|
||||
// Handle click outside
|
||||
useEffect(() => {
|
||||
if (!open) return
|
||||
const handleClick = (e) => {
|
||||
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
||||
onDismiss?.()
|
||||
}
|
||||
}
|
||||
// Delay to avoid triggering on the same click that opened the menu
|
||||
const timer = setTimeout(() => {
|
||||
window.addEventListener('click', handleClick)
|
||||
}, 50)
|
||||
return () => {
|
||||
clearTimeout(timer)
|
||||
window.removeEventListener('click', handleClick)
|
||||
}
|
||||
}, [open, onDismiss])
|
||||
|
||||
// Calculate which wedge the pointer is over
|
||||
const getWedgeAtPoint = useCallback((clientX, clientY) => {
|
||||
const dx = clientX - x
|
||||
|
|
@ -109,6 +91,17 @@ export default function RadialMenu({
|
|||
onDismiss?.()
|
||||
}, [getWedgeAtPoint, lat, lon, onDismiss])
|
||||
|
||||
// Handle backdrop click (dismiss menu)
|
||||
const handleBackdropClick = useCallback((e) => {
|
||||
e.stopPropagation()
|
||||
onDismiss?.()
|
||||
}, [onDismiss])
|
||||
|
||||
// Prevent menu container clicks from reaching backdrop
|
||||
const handleContainerClick = useCallback((e) => {
|
||||
e.stopPropagation()
|
||||
}, [])
|
||||
|
||||
// Generate wedge paths
|
||||
const generateWedgePath = (index) => {
|
||||
const startAngle = (index * wedgeAngle - 90) * (Math.PI / 180)
|
||||
|
|
@ -144,9 +137,25 @@ export default function RadialMenu({
|
|||
const clampedY = Math.max(padding, Math.min(window.innerHeight - padding, y))
|
||||
|
||||
const content = (
|
||||
<>
|
||||
{/* Full-screen transparent backdrop for dismiss */}
|
||||
<div
|
||||
onClick={handleBackdropClick}
|
||||
onContextMenu={handleBackdropClick}
|
||||
style={{
|
||||
position: 'fixed',
|
||||
inset: 0,
|
||||
zIndex: 9998,
|
||||
background: 'transparent',
|
||||
cursor: 'default',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Radial menu container */}
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="radial-menu-container"
|
||||
onClick={handleContainerClick}
|
||||
style={{
|
||||
position: 'fixed',
|
||||
left: clampedX,
|
||||
|
|
@ -264,6 +273,7 @@ export default function RadialMenu({
|
|||
}
|
||||
`}</style>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
return createPortal(content, document.body)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue