Skip to content

Commit

Permalink
fix(tooltip): show at most one tooltip at a time (#6522)
Browse files Browse the repository at this point in the history
* fix(tooltip): show at most one tooltip at a time

* fix(tooltip): ensure to use the correct reference to `window` and `document`

* refactor: do not use useForceUpdate

Co-authored-by: Segun Adebayo <joseshegs@gmail.com>
  • Loading branch information
itkrt2y and segunadebayo committed Aug 22, 2022
1 parent f5beff8 commit dcd9eab
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/rich-cougars-sin.md
@@ -0,0 +1,5 @@
---
"@chakra-ui/tooltip": patch
---

Show at most one tooltip at a time
38 changes: 33 additions & 5 deletions packages/tooltip/src/use-tooltip.ts
Expand Up @@ -4,7 +4,7 @@ import { popperCSSVars, usePopper, UsePopperProps } from "@chakra-ui/popper"
import { mergeRefs } from "@chakra-ui/react-use-merge-refs"
import { PropGetter } from "@chakra-ui/react-types"
import { callAllHandlers } from "@chakra-ui/shared-utils"
import { useCallback, useEffect, useRef, useId } from "react"
import { useCallback, useEffect, useRef, useId, type RefObject } from "react"

export interface UseTooltipProps
extends Pick<
Expand Down Expand Up @@ -120,19 +120,34 @@ export function useTooltip(props: UseTooltipProps = {}) {
const enterTimeout = useRef<number>()
const exitTimeout = useRef<number>()

const closeNow = useCallback(() => {
if (exitTimeout.current) {
clearTimeout(exitTimeout.current)
exitTimeout.current = undefined
}
onClose()
}, [onClose])

const dispatchCloseEvent = useCloseEvent(ref, closeNow)

const openWithDelay = useCallback(() => {
if (!isDisabled && !enterTimeout.current) {
enterTimeout.current = window.setTimeout(onOpen, openDelay)
dispatchCloseEvent()
enterTimeout.current =
ref.current?.ownerDocument?.defaultView?.setTimeout(onOpen, openDelay)
}
}, [isDisabled, onOpen, openDelay])
}, [dispatchCloseEvent, isDisabled, onOpen, openDelay])

const closeWithDelay = useCallback(() => {
if (enterTimeout.current) {
clearTimeout(enterTimeout.current)
enterTimeout.current = undefined
}
exitTimeout.current = window.setTimeout(onClose, closeDelay)
}, [closeDelay, onClose])
exitTimeout.current = ref.current?.ownerDocument?.defaultView?.setTimeout(
closeNow,
closeDelay,
)
}, [closeDelay, closeNow])

const onClick = useCallback(() => {
if (isOpen && closeOnClick) {
Expand Down Expand Up @@ -262,3 +277,16 @@ export function useTooltip(props: UseTooltipProps = {}) {
}

export type UseTooltipReturn = ReturnType<typeof useTooltip>

const closeEventName = "chakra-ui:close-tooltip"

function useCloseEvent(ref: RefObject<Element>, close: () => void) {
useEffect(() => {
const doc = ref.current?.ownerDocument
doc?.addEventListener(closeEventName, close)
return () => doc?.removeEventListener(closeEventName, close)
}, [close, ref])

return () =>
ref.current?.ownerDocument?.dispatchEvent(new CustomEvent(closeEventName))
}

1 comment on commit dcd9eab

@vercel
Copy link

@vercel vercel bot commented on dcd9eab Aug 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.