diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6e1d68993..bf77e4618 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,7 +65,7 @@ importers: version: 5.0.0(semantic-release@24.0.0(typescript@5.5.3)) '@sanity/ui-workshop': specifier: ^2.0.15 - version: 2.0.15(@sanity/icons@3.3.0(react@18.3.1))(@sanity/ui@2.6.3(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(@types/node@20.12.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.30.3) + version: 2.0.15(@sanity/icons@3.3.0(react@18.3.1))(@sanity/ui@2.6.5(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(@types/node@20.12.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.30.3) '@storybook/addon-a11y': specifier: ^8.2.1 version: 8.2.1(storybook@8.2.1(@babel/preset-env@7.24.7(@babel/core@7.24.7))) @@ -1861,8 +1861,8 @@ packages: react-dom: ^18 styled-components: ^5.2 || ^6 - '@sanity/ui@2.6.3': - resolution: {integrity: sha512-qyNaIlfRvLQ21Z4+PP61qZ/Rjbk2UqqC/YTS9AmeRvetL9WEuUYFbMrprdKzAAUcWOqabBZVLjrU9F01nDEtmw==} + '@sanity/ui@2.6.5': + resolution: {integrity: sha512-9IDql5kxx3Rloed8apTHu4soQfgQg7j72vd97IA9g05hjHfpuDWVpwK0P1Yvgb2wQvNYC1IMsyCNpLZTL9fWrw==} engines: {node: '>=14.0.0'} peerDependencies: react: ^18 @@ -6497,7 +6497,7 @@ packages: react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: - react: ^18.3.1 + react: '*' react-element-to-jsx-string@15.0.0: resolution: {integrity: sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==} @@ -9676,10 +9676,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@sanity/ui-workshop@2.0.15(@sanity/icons@3.3.0(react@18.3.1))(@sanity/ui@2.6.3(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(@types/node@20.12.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.30.3)': + '@sanity/ui-workshop@2.0.15(@sanity/icons@3.3.0(react@18.3.1))(@sanity/ui@2.6.5(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(@types/node@20.12.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.30.3)': dependencies: '@sanity/icons': 3.3.0(react@18.3.1) - '@sanity/ui': 2.6.3(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + '@sanity/ui': 2.6.5(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) '@vitejs/plugin-react': 4.3.0(vite@5.3.3(@types/node@20.12.7)(terser@5.30.3)) axe-core: 4.9.1 cac: 6.7.14 @@ -9709,7 +9709,7 @@ snapshots: - supports-color - terser - '@sanity/ui@2.6.3(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1))': + '@sanity/ui@2.6.5(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)(styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1))': dependencies: '@floating-ui/react-dom': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@sanity/color': 3.0.6 @@ -9721,6 +9721,7 @@ snapshots: react-is: 18.3.1 react-refractor: 2.2.0(react@18.3.1) styled-components: 6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + use-effect-event: 1.0.2(react@18.3.1) '@sec-ant/readable-stream@0.4.1': {} diff --git a/src/core/primitives/tooltip/tooltip.tsx b/src/core/primitives/tooltip/tooltip.tsx index 9bc1a7bb6..1f9754c3e 100644 --- a/src/core/primitives/tooltip/tooltip.tsx +++ b/src/core/primitives/tooltip/tooltip.tsx @@ -268,6 +268,9 @@ export const Tooltip = forwardRef(function Tooltip( [childProp?.props, handleIsOpenChange], ) + // Handle closing the tooltip when the mouse leaves the referenceElement + useCloseOnMouseLeave({handleIsOpenChange, referenceElement, showTooltip}) + // Close when `disabled` changes to `true` useEffect(() => { if (disabled && showTooltip) handleIsOpenChange(false) @@ -298,9 +301,6 @@ export const Tooltip = forwardRef(function Tooltip( } }, [handleIsOpenChange, showTooltip]) - // Handle closing the tooltip when the mouse leaves the referenceElement - useCloseOnMouseLeave({handleIsOpenChange, referenceElement, showTooltip}) - // // Set the max width of the tooltip based on boundaries and portals useLayoutEffect(() => { // Get the maximum tooltip width (sans tooltip padding) @@ -446,7 +446,7 @@ function useCloseOnMouseLeave({ // Since we don't want the `mouseevent` events to be attached and removed if the `referenceElement` is changed // we use a "effect event" (https://19.react.dev/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events) // in order to always see the latest `referenceElement` value inside the event handler itself. - const onMouseMove = useEffectEvent((target: EventTarget | null) => { + const onMouseMove = useEffectEvent((target: EventTarget | null, teardown: () => void) => { if (!referenceElement) return const isHoveringReference = @@ -454,6 +454,8 @@ function useCloseOnMouseLeave({ if (!isHoveringReference) { handleIsOpenChange(false) + // Allow removing the event listener eagerly, to avoid race conditions + teardown() } }) @@ -464,7 +466,7 @@ function useCloseOnMouseLeave({ if (!showTooltip) return const handleMouseMove = (event: MouseEvent) => { - onMouseMove(event.target) + onMouseMove(event.target, () => window.removeEventListener('mousemove', handleMouseMove)) } window.addEventListener('mousemove', handleMouseMove)