Skip to content

Commit

Permalink
fix: add fallback if onTransitionEnd never fires
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrieljablonski committed Dec 27, 2023
1 parent 7b83b18 commit 44fc0ed
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
24 changes: 20 additions & 4 deletions src/components/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useTooltip } from 'components/TooltipProvider'
import useIsomorphicLayoutEffect from 'utils/use-isomorphic-layout-effect'
import { getScrollParent } from 'utils/get-scroll-parent'
import { computeTooltipPosition } from 'utils/compute-positions'
import { cssTimeToMs } from 'utils/css-time-to-ms'
import coreStyles from './core-styles.module.css'
import styles from './styles.module.css'
import type {
Expand Down Expand Up @@ -67,6 +68,7 @@ const Tooltip = ({
const tooltipArrowRef = useRef<HTMLElement>(null)
const tooltipShowDelayTimerRef = useRef<NodeJS.Timeout | null>(null)
const tooltipHideDelayTimerRef = useRef<NodeJS.Timeout | null>(null)
const missedTransitionTimerRef = useRef<NodeJS.Timeout | null>(null)
const [actualPlacement, setActualPlacement] = useState(place)
const [inlineStyles, setInlineStyles] = useState({})
const [inlineArrowStyles, setInlineArrowStyles] = useState({})
Expand Down Expand Up @@ -211,13 +213,28 @@ const Tooltip = ({
if (show === wasShowing.current) {
return
}
if (missedTransitionTimerRef.current) {
clearTimeout(missedTransitionTimerRef.current)
}
wasShowing.current = show
if (show) {
afterShow?.()
} else {
/**
* see `onTransitionEnd` on tooltip wrapper
*/
const style = getComputedStyle(document.body)
const transitionShowDelay = cssTimeToMs(style.getPropertyValue('--rt-transition-show-delay'))
missedTransitionTimerRef.current = setTimeout(() => {
/**
* if the tooltip switches from `show === true` to `show === false` too fast
* the transition never runs, so `onTransitionEnd` callback never gets fired
*/
setRendered(false)
setImperativeOptions(null)
afterHide?.()
// +25ms just to make sure `onTransitionEnd` (if it gets fired) has time to run
}, transitionShowDelay + 25)
}
}, [show])

Expand Down Expand Up @@ -811,10 +828,9 @@ const Tooltip = ({
clickable && coreStyles['clickable'],
)}
onTransitionEnd={(event: TransitionEvent) => {
/**
* @warning if `--rt-transition-closing-delay` is set to 0,
* the tooltip will be stuck (but not visible) on the DOM
*/
if (missedTransitionTimerRef.current) {
clearTimeout(missedTransitionTimerRef.current)
}
if (show || event.propertyName !== 'opacity') {
return
}
Expand Down
11 changes: 11 additions & 0 deletions src/utils/css-time-to-ms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const cssTimeToMs = (time: string): number => {
const match = time.match(/^([\d.]+)(m?s?)$/)
if (!match) {
return 0
}
const [, amount, unit] = match
if (unit !== 's' && unit !== 'ms') {
return 0
}
return Number(amount) * (unit === 'ms' ? 1 : 1000)
}

0 comments on commit 44fc0ed

Please sign in to comment.