From 7e08c183fb2ee39927df6dc0387dbe76b1dfb1e4 Mon Sep 17 00:00:00 2001 From: storywithoutend Date: Mon, 11 Sep 2023 22:20:09 +0800 Subject: [PATCH] fix dynamic popover hover + record item docs --- .../atoms/DynamicPopover/DynamicPopover.tsx | 59 +++++++++++++++++-- .../components/molecules/Tooltip/Tooltip.tsx | 1 - .../reference/mdx/atoms/RecordItem.docs.mdx | 34 +++++------ 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/components/src/components/atoms/DynamicPopover/DynamicPopover.tsx b/components/src/components/atoms/DynamicPopover/DynamicPopover.tsx index 5ab860c7..ee6b1ce5 100644 --- a/components/src/components/atoms/DynamicPopover/DynamicPopover.tsx +++ b/components/src/components/atoms/DynamicPopover/DynamicPopover.tsx @@ -2,6 +2,8 @@ import * as React from 'react' import styled, { css } from 'styled-components' import { TransitionState, useTransition } from 'react-transition-state' +import { debounce } from 'lodash' + import { mq } from '@/src/utils/responsiveHelpers' import { Portal } from '../Portal' @@ -121,6 +123,19 @@ const defaultAnimationFunc: DynamicPopoverAnimationFunc = ( return { translate, mobileTranslate } } +const checkRectContainsPoint = ( + rect?: DOMRect, + point?: { x: number; y: number }, +) => { + if (!rect || !point) return false + return ( + point.x >= rect.x && + point.x <= rect.x + rect.width && + point.y >= rect.y && + point.y <= rect.y + rect.height + ) +} + const makeWidth = (width: number | string) => typeof width === 'number' ? `${width}px` : width @@ -201,6 +216,7 @@ const PopoverContainer = styled.div<{ transition: opacity ${$transitionDuration}ms ease-in-out; top: ${$y}px; left: ${$x}px; + pointer-events: initial; ${$isControlled && css` @@ -358,30 +374,57 @@ export const DynamicPopover = ({ ) }, [_animationFn]) + // Attach and remove event listeners React.useEffect(() => { - setPosition() - const handleResize = () => { setPosition() } + const popoverElement = popoverContainerRef?.current const targetElement = anchorRef?.current - let handleMouseEnter: () => void - let handleMouseLeave: () => void + let handleMouseEnter: (e: MouseEvent) => void + let handleMouseLeave: (e: MouseEvent) => void + let handleMouseMove: (e: MouseEvent) => void if (!isControlled) { handleMouseEnter = () => { - setPosition() toggle(true) onShowCallback?.() } + const debouncedMouseMove = debounce( + (e: MouseEvent) => { + const cursorXY = { x: e.clientX, y: e.clientY } + const targetRect = targetElement?.getBoundingClientRect() + const popoverRect = popoverElement?.getBoundingClientRect() + + const targetContainsPoint = checkRectContainsPoint( + targetRect, + cursorXY, + ) + const popoverContainsPoint = checkRectContainsPoint( + popoverRect, + cursorXY, + ) + if (!targetContainsPoint && !popoverContainsPoint) toggle(false) + document.removeEventListener('mousemove', handleMouseMove) + }, + 100, + { maxWait: 1000 }, + ) + + handleMouseMove = (e: MouseEvent) => { + debouncedMouseMove(e) + } + handleMouseLeave = () => { - toggle(false) + document.addEventListener('mousemove', handleMouseMove) } targetElement?.addEventListener('mouseenter', handleMouseEnter) targetElement?.addEventListener('mouseleave', handleMouseLeave) + popoverElement?.addEventListener('mouseenter', handleMouseEnter) + popoverElement?.addEventListener('mouseleave', handleMouseLeave) } addEventListener('resize', handleResize) @@ -390,6 +433,9 @@ export const DynamicPopover = ({ if (!isControlled) { targetElement?.removeEventListener('mouseenter', handleMouseEnter) targetElement?.removeEventListener('mouseleave', handleMouseLeave) + popoverElement?.removeEventListener('mouseenter', handleMouseEnter) + popoverElement?.removeEventListener('mouseleave', handleMouseLeave) + document.removeEventListener('mousemove', handleMouseMove) } removeEventListener('resize', handleResize) } @@ -397,6 +443,7 @@ export const DynamicPopover = ({ placement, mobilePlacement, setPosition, + positionState, additionalGap, onShowCallback, anchorRef, diff --git a/components/src/components/molecules/Tooltip/Tooltip.tsx b/components/src/components/molecules/Tooltip/Tooltip.tsx index 6d0a1ad8..8b185be3 100644 --- a/components/src/components/molecules/Tooltip/Tooltip.tsx +++ b/components/src/components/molecules/Tooltip/Tooltip.tsx @@ -78,7 +78,6 @@ const TooltipPopoverElement = styled.div<{ }>( ({ theme, $background, $placement, $mobilePlacement }) => css` position: relative; - pointer-events: none; box-sizing: border-box; filter: drop-shadow(0px 0px 1px #e8e8e8) drop-shadow(0px 2px 4px rgba(0, 0, 0, 0.2)); diff --git a/docs/src/reference/mdx/atoms/RecordItem.docs.mdx b/docs/src/reference/mdx/atoms/RecordItem.docs.mdx index 0de2f149..a1c96a7d 100644 --- a/docs/src/reference/mdx/atoms/RecordItem.docs.mdx +++ b/docs/src/reference/mdx/atoms/RecordItem.docs.mdx @@ -8,7 +8,7 @@ import { RecordItem } from '@ensdomains/thorin' ``` ```tsx live=true expand=true -}>user#123 +} value="user#123">user#123 ``` ## Props @@ -19,16 +19,16 @@ import { RecordItem } from '@ensdomains/thorin' ```tsx live=true - + 0xb794f5ea0ba39494ce839613fffba74279579268 - }> + } value="0xb794f5ea0ba39494ce839613fffba74279579268"> 0xb794f5ea0ba39494ce839613fffba74279579268 - + 0xb794...9268 - } inline> + } inline value="0xb794f5ea0ba39494ce839613fffba74279579268"> 0xb794...9268 @@ -38,16 +38,16 @@ import { RecordItem } from '@ensdomains/thorin' ```tsx live=true - } size="small"> + } size="small" value="Small with icon"> Small with icon - } size="large"> + } size="large" value="Large with icon"> Large with icon - + Small with label - + Large with label @@ -57,28 +57,28 @@ import { RecordItem } from '@ensdomains/thorin' ```tsx live=true - } size="small"> + } size="small" value="Small with icon"> Small with icon - + Small with label - } size="large"> + } size="large" value="Large with icon"> Large with icon - + Large with label - } inline size="small"> + } inline size="small" value="Small and inline with icon"> Small and inline with icon - + Small and inline with label - } inline size="large"> + } inline size="large" value="Large and inline with icon"> Large and inline with icon - + Large and inline with label