Skip to content

Commit 0a6aed9

Browse files
committed
refactor(tooltip): Cleaned up some useTooltip code
1 parent 6c760ec commit 0a6aed9

File tree

1 file changed

+47
-50
lines changed

1 file changed

+47
-50
lines changed

packages/tooltip/src/useTooltip.ts

Lines changed: 47 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,19 @@ import {
1313
import cn from "classnames";
1414
import { TransitionHooks, useFixedPositioning } from "@react-md/transition";
1515
import {
16-
HorizontalPosition,
16+
ABOVE_CENTER_ANCHOR,
17+
BELOW_CENTER_ANCHOR,
18+
CENTER_LEFT_ANCHOR,
19+
CENTER_RIGHT_ANCHOR,
1720
HoverModeEventHandlers,
1821
HoverModeOnlyReturnValue,
22+
PositionAnchor,
23+
SimplePosition,
1924
unitToNumber,
2025
useHoverMode,
2126
useOnUnmount,
2227
UserInteractionMode,
2328
useUserInteractionMode,
24-
VerticalPosition,
2529
} from "@react-md/utils";
2630

2731
import {
@@ -39,11 +43,27 @@ import {
3943
useTooltipPosition,
4044
} from "./useTooltipPosition";
4145

46+
/** @internal */
47+
function getAnchor(position: SimplePosition): PositionAnchor {
48+
switch (position) {
49+
case "above":
50+
return ABOVE_CENTER_ANCHOR;
51+
case "below":
52+
return BELOW_CENTER_ANCHOR;
53+
case "left":
54+
return CENTER_LEFT_ANCHOR;
55+
case "right":
56+
return CENTER_RIGHT_ANCHOR;
57+
default:
58+
throw new Error(`Invalid position: ${position}`);
59+
}
60+
}
61+
4262
/**
4363
* @internal
4464
* @remarks \@since 2.8.0
4565
*/
46-
export type TooltipInitiated = UserInteractionMode | null;
66+
export type TooltipInitiatedBy = UserInteractionMode | null;
4767

4868
/** @remarks \@since 2.8.0 */
4969
export type TooltipTouchEventHandlers<E extends HTMLElement> = Pick<
@@ -302,7 +322,7 @@ export function useTooltip<E extends HTMLElement>({
302322
onEntered,
303323
onExited,
304324
disableSwapping,
305-
disableHoverMode,
325+
disableHoverMode: disabled,
306326
disableAutoSpacing = process.env.NODE_ENV === "test",
307327
}: TooltipHookOptions<E>): TooltipHookReturnValue<E> {
308328
const containerRef = useRef<E | null>(null);
@@ -311,54 +331,52 @@ export function useTooltip<E extends HTMLElement>({
311331
defaultPosition,
312332
threshold,
313333
});
314-
const horizontal = position === "left" || position === "right";
315334
const mode = useUserInteractionMode();
316-
const [touched, setTouched] = useState(false);
317-
const initiated = useRef<TooltipInitiated>(null);
335+
const [initiatedBy, setInitiatedBy] = useState<TooltipInitiatedBy>(null);
318336
const windowFocusEvent = useRef(false);
319337
const timeout = useRef<number | undefined>(undefined);
320338
const {
321339
visible,
322340
setVisible,
323341
handlers: mouseHandlers,
342+
disableHoverMode,
324343
...others
325344
} = useHoverMode<E>({
326-
disabled: disableHoverMode,
345+
disabled,
327346
onMouseEnter: (event) => {
328347
onMouseEnter?.(event);
329-
if (initiated.current !== null) {
348+
if (initiatedBy !== null) {
330349
event.stopPropagation();
331350
return;
332351
}
333352

334-
initiated.current = "mouse";
335353
containerRef.current = event.currentTarget;
336354
updatePosition(event.currentTarget);
355+
setInitiatedBy("mouse");
337356
},
338357
onMouseLeave: (event) => {
339358
onMouseLeave?.(event);
340-
if (initiated.current !== "mouse") {
359+
if (initiatedBy !== "mouse") {
341360
event.stopPropagation();
342361
return;
343362
}
344363

345-
initiated.current = null;
364+
setInitiatedBy(null);
346365
},
347366
});
348367
const hide = useCallback(() => {
349-
initiated.current = null;
350368
window.clearTimeout(timeout.current);
351369
setVisible(false);
370+
setInitiatedBy(null);
352371
}, [setVisible]);
353372

354373
const onBlur = (event: FocusEvent<E>): void => {
355374
propOnBlur?.(event);
356375

357-
if (initiated.current !== "keyboard") {
376+
if (initiatedBy !== "keyboard") {
358377
return;
359378
}
360379

361-
window.clearTimeout(timeout.current);
362380
hide();
363381
};
364382
const onFocus = (event: FocusEvent<E>): void => {
@@ -371,11 +389,11 @@ export function useTooltip<E extends HTMLElement>({
371389
return;
372390
}
373391

374-
if (mode !== "keyboard" || initiated.current !== null) {
392+
if (mode !== "keyboard" || initiatedBy !== null) {
375393
return;
376394
}
377395

378-
initiated.current = "keyboard";
396+
setInitiatedBy("keyboard");
379397
window.clearTimeout(timeout.current);
380398
containerRef.current = event.currentTarget;
381399
updatePosition(event.currentTarget);
@@ -387,11 +405,10 @@ export function useTooltip<E extends HTMLElement>({
387405
const onKeyDown = (event: KeyboardEvent<E>): void => {
388406
propOnKeyDown?.(event);
389407

390-
if (initiated.current !== "keyboard" || event.key !== "Escape") {
408+
if (initiatedBy !== "keyboard" || event.key !== "Escape") {
391409
return;
392410
}
393411

394-
window.clearTimeout(timeout.current);
395412
hide();
396413
};
397414

@@ -402,8 +419,7 @@ export function useTooltip<E extends HTMLElement>({
402419
return;
403420
}
404421

405-
initiated.current = "touch";
406-
setTouched(true);
422+
setInitiatedBy("touch");
407423
window.clearTimeout(timeout.current);
408424
timeout.current = window.setTimeout(() => {
409425
setVisible(true);
@@ -453,43 +469,27 @@ export function useTooltip<E extends HTMLElement>({
453469
};
454470
}, [hide, mode]);
455471
useEffect(() => {
456-
if (mode !== "touch") {
472+
if (initiatedBy !== "touch") {
457473
return;
458474
}
459475

476+
window.addEventListener("touchmove", hide);
460477
window.addEventListener("touchend", hide);
461478
return () => {
479+
window.removeEventListener("touchmove", hide);
462480
window.removeEventListener("touchend", hide);
463481
};
464-
}, [hide, mode]);
465-
useEffect(() => {
466-
if (!touched) {
467-
return;
468-
}
469-
470-
// need to cancel the tooltip appearance if a touchmove event occurs before
471-
// the tooltip appears since it means the page will scroll
472-
const handler = (): void => {
473-
initiated.current = null;
474-
window.clearTimeout(timeout.current);
475-
setTouched(false);
476-
setVisible(false);
477-
};
482+
}, [hide, initiatedBy, setVisible]);
478483

479-
window.addEventListener("touchmove", handler);
480-
return () => {
481-
window.removeEventListener("touchmove", handler);
482-
};
483-
}, [setVisible, touched]);
484+
useOnUnmount(() => {
485+
window.clearTimeout(timeout.current);
486+
});
484487

485488
const { updateStyle: _u, ...positionProps } = useFixedPositioning({
486489
style,
487-
anchor: {
488-
x: horizontal ? (position as HorizontalPosition) : "center",
489-
y: horizontal ? "center" : (position as VerticalPosition),
490-
},
490+
anchor: getAnchor(position),
491491
disableSwapping: disableSwapping ?? !!determinedPosition,
492-
fixedTo: containerRef.current,
492+
fixedTo: containerRef,
493493
getOptions: (node) => {
494494
let tooltipSpacing = dense ? denseSpacing : spacing;
495495
/* istanbul ignore next */
@@ -516,10 +516,6 @@ export function useTooltip<E extends HTMLElement>({
516516
onExited,
517517
});
518518

519-
useOnUnmount(() => {
520-
window.clearTimeout(timeout.current);
521-
});
522-
523519
const tooltipHandlers: Required<TooltippedElementEventHandlers<E>> = {
524520
...mouseHandlers,
525521
onFocus,
@@ -550,5 +546,6 @@ export function useTooltip<E extends HTMLElement>({
550546
handlers: tooltipHandlers,
551547
elementProps,
552548
tooltipProps,
549+
disableHoverMode,
553550
};
554551
}

0 commit comments

Comments
 (0)