Skip to content

Commit

Permalink
refactor(tooltip): Cleaned up some useTooltip code
Browse files Browse the repository at this point in the history
  • Loading branch information
mlaursen committed Apr 20, 2021
1 parent 6c760ec commit 0a6aed9
Showing 1 changed file with 47 additions and 50 deletions.
97 changes: 47 additions & 50 deletions packages/tooltip/src/useTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@ import {
import cn from "classnames";
import { TransitionHooks, useFixedPositioning } from "@react-md/transition";
import {
HorizontalPosition,
ABOVE_CENTER_ANCHOR,
BELOW_CENTER_ANCHOR,
CENTER_LEFT_ANCHOR,
CENTER_RIGHT_ANCHOR,
HoverModeEventHandlers,
HoverModeOnlyReturnValue,
PositionAnchor,
SimplePosition,
unitToNumber,
useHoverMode,
useOnUnmount,
UserInteractionMode,
useUserInteractionMode,
VerticalPosition,
} from "@react-md/utils";

import {
Expand All @@ -39,11 +43,27 @@ import {
useTooltipPosition,
} from "./useTooltipPosition";

/** @internal */
function getAnchor(position: SimplePosition): PositionAnchor {
switch (position) {
case "above":
return ABOVE_CENTER_ANCHOR;
case "below":
return BELOW_CENTER_ANCHOR;
case "left":
return CENTER_LEFT_ANCHOR;
case "right":
return CENTER_RIGHT_ANCHOR;
default:
throw new Error(`Invalid position: ${position}`);
}
}

/**
* @internal
* @remarks \@since 2.8.0
*/
export type TooltipInitiated = UserInteractionMode | null;
export type TooltipInitiatedBy = UserInteractionMode | null;

/** @remarks \@since 2.8.0 */
export type TooltipTouchEventHandlers<E extends HTMLElement> = Pick<
Expand Down Expand Up @@ -302,7 +322,7 @@ export function useTooltip<E extends HTMLElement>({
onEntered,
onExited,
disableSwapping,
disableHoverMode,
disableHoverMode: disabled,
disableAutoSpacing = process.env.NODE_ENV === "test",
}: TooltipHookOptions<E>): TooltipHookReturnValue<E> {
const containerRef = useRef<E | null>(null);
Expand All @@ -311,54 +331,52 @@ export function useTooltip<E extends HTMLElement>({
defaultPosition,
threshold,
});
const horizontal = position === "left" || position === "right";
const mode = useUserInteractionMode();
const [touched, setTouched] = useState(false);
const initiated = useRef<TooltipInitiated>(null);
const [initiatedBy, setInitiatedBy] = useState<TooltipInitiatedBy>(null);
const windowFocusEvent = useRef(false);
const timeout = useRef<number | undefined>(undefined);
const {
visible,
setVisible,
handlers: mouseHandlers,
disableHoverMode,
...others
} = useHoverMode<E>({
disabled: disableHoverMode,
disabled,
onMouseEnter: (event) => {
onMouseEnter?.(event);
if (initiated.current !== null) {
if (initiatedBy !== null) {
event.stopPropagation();
return;
}

initiated.current = "mouse";
containerRef.current = event.currentTarget;
updatePosition(event.currentTarget);
setInitiatedBy("mouse");
},
onMouseLeave: (event) => {
onMouseLeave?.(event);
if (initiated.current !== "mouse") {
if (initiatedBy !== "mouse") {
event.stopPropagation();
return;
}

initiated.current = null;
setInitiatedBy(null);
},
});
const hide = useCallback(() => {
initiated.current = null;
window.clearTimeout(timeout.current);
setVisible(false);
setInitiatedBy(null);
}, [setVisible]);

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

if (initiated.current !== "keyboard") {
if (initiatedBy !== "keyboard") {
return;
}

window.clearTimeout(timeout.current);
hide();
};
const onFocus = (event: FocusEvent<E>): void => {
Expand All @@ -371,11 +389,11 @@ export function useTooltip<E extends HTMLElement>({
return;
}

if (mode !== "keyboard" || initiated.current !== null) {
if (mode !== "keyboard" || initiatedBy !== null) {
return;
}

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

if (initiated.current !== "keyboard" || event.key !== "Escape") {
if (initiatedBy !== "keyboard" || event.key !== "Escape") {
return;
}

window.clearTimeout(timeout.current);
hide();
};

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

initiated.current = "touch";
setTouched(true);
setInitiatedBy("touch");
window.clearTimeout(timeout.current);
timeout.current = window.setTimeout(() => {
setVisible(true);
Expand Down Expand Up @@ -453,43 +469,27 @@ export function useTooltip<E extends HTMLElement>({
};
}, [hide, mode]);
useEffect(() => {
if (mode !== "touch") {
if (initiatedBy !== "touch") {
return;
}

window.addEventListener("touchmove", hide);
window.addEventListener("touchend", hide);
return () => {
window.removeEventListener("touchmove", hide);
window.removeEventListener("touchend", hide);
};
}, [hide, mode]);
useEffect(() => {
if (!touched) {
return;
}

// need to cancel the tooltip appearance if a touchmove event occurs before
// the tooltip appears since it means the page will scroll
const handler = (): void => {
initiated.current = null;
window.clearTimeout(timeout.current);
setTouched(false);
setVisible(false);
};
}, [hide, initiatedBy, setVisible]);

window.addEventListener("touchmove", handler);
return () => {
window.removeEventListener("touchmove", handler);
};
}, [setVisible, touched]);
useOnUnmount(() => {
window.clearTimeout(timeout.current);
});

const { updateStyle: _u, ...positionProps } = useFixedPositioning({
style,
anchor: {
x: horizontal ? (position as HorizontalPosition) : "center",
y: horizontal ? "center" : (position as VerticalPosition),
},
anchor: getAnchor(position),
disableSwapping: disableSwapping ?? !!determinedPosition,
fixedTo: containerRef.current,
fixedTo: containerRef,
getOptions: (node) => {
let tooltipSpacing = dense ? denseSpacing : spacing;
/* istanbul ignore next */
Expand All @@ -516,10 +516,6 @@ export function useTooltip<E extends HTMLElement>({
onExited,
});

useOnUnmount(() => {
window.clearTimeout(timeout.current);
});

const tooltipHandlers: Required<TooltippedElementEventHandlers<E>> = {
...mouseHandlers,
onFocus,
Expand Down Expand Up @@ -550,5 +546,6 @@ export function useTooltip<E extends HTMLElement>({
handlers: tooltipHandlers,
elementProps,
tooltipProps,
disableHoverMode,
};
}

0 comments on commit 0a6aed9

Please sign in to comment.