Skip to content

Commit

Permalink
feat!(utils): Updated the HoverMode API
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The `useHoverMode` hook no longer returns
`stickyHandlers` and instead returns `hoverHandlers` that only include
`onMouseEnter` and `onMouseLeave`. The `handlers` that are returned now
include `onClick`, `onMouseEnter`, and `onMouseLeave`. This was kind of
what the `stickyHandlers` was before. In addition, clicking an element
no longer disabled the hover mode behavior.

BREAKING CHANGE: The `useHoverMode` hook no longer accepts an
`HTMLElement` generic and instead the event handlers will automatically
infer the `HTMLElement` based on usage.

BREAKING CHANGE: `DEFAULT_HOVER_MODE_STICKY_EXIT_TIME` has been renamed to
`DEFAULT_HOVER_MODE_EXIT_TIME`.

BREAKING CHANGE: The following typescript types have been removed:
`HoverModeOnlyOptions`, `HoverModeOnlyReturnValue`

BREAKING CHANGE: The `exitVisibilityDelay` always defaults to
`DEFAULT_HOVER_MODE_EXIT_TIME`.
  • Loading branch information
mlaursen committed Jan 30, 2022
1 parent 2752a98 commit ac60bdb
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 252 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@ import { DialogContent, FixedDialog } from "@react-md/dialog";
import { BELOW_CENTER_ANCHOR, useHoverMode } from "@react-md/utils";

export default function StickyHoverMode(): ReactElement {
const { stuck, active, handlers, stickyHandlers, visible, setVisible } =
useHoverMode({
sticky: true,
});
const { stuck, active, handlers, hoverHandlers, visible, setVisible } =
useHoverMode();
const buttonRef = useRef<HTMLButtonElement>(null);

return (
<>
<Button {...stickyHandlers} ref={buttonRef}>
<Button {...handlers} ref={buttonRef}>
Button
</Button>
<FixedDialog
{...handlers}
{...hoverHandlers}
aria-label="Additional Information"
id="some-dialog-id"
visible={visible}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,22 @@ export default function WikipediaPreviewLink({
children,
}: WikipediaPreviewLinkProps): ReactElement {
const id = useId("wiki");
const { active, handlers, visible, setVisible } = useHoverMode();
const { active, hoverHandlers, visible, setVisible } = useHoverMode({
exitVisibilityDelay: 0,
});

const linkRef = useRef<HTMLAnchorElement>(null);
return (
<>
<Link ref={linkRef} href={href} {...handlers}>
<Link ref={linkRef} href={href} {...hoverHandlers}>
{children}
</Link>
<FixedDialog
aria-label="Wikipedia Preview"
id={id}
visible={visible}
onRequestClose={() => setVisible(false)}
{...handlers}
{...hoverHandlers}
fixedTo={linkRef}
onClick={() => {
window.location.href = href;
Expand Down
82 changes: 44 additions & 38 deletions packages/tooltip/src/useTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
CENTER_LEFT_ANCHOR,
CENTER_RIGHT_ANCHOR,
HoverModeEventHandlers,
HoverModeOnlyReturnValue,
HoverModeHookReturnValue,
PositionAnchor,
SimplePosition,
unitToNumber,
Expand Down Expand Up @@ -89,9 +89,9 @@ export type TooltipKeyboardEventHandlers<E extends HTMLElement> = Pick<
* @remarks \@since 2.8.0
*/
export type TooltippedElementEventHandlers<E extends HTMLElement> =
HoverModeEventHandlers<E> &
TooltipTouchEventHandlers<E> &
TooltipKeyboardEventHandlers<E>;
TooltipTouchEventHandlers<E> &
TooltipKeyboardEventHandlers<E> &
Pick<HTMLAttributes<E>, keyof HoverModeEventHandlers>;

/** @remarks \@since 2.8.0 */
export interface TooltipHookProvidedElementProps<E extends HTMLElement>
Expand Down Expand Up @@ -245,7 +245,7 @@ export type TooltipHookProvidedTooltipProps = Pick<TooltipProps, "style"> &
* @remarks \@since 2.8.0
*/
export interface TooltipHookReturnValue<E extends HTMLElement>
extends Omit<HoverModeOnlyReturnValue<E>, "handlers"> {
extends Omit<HoverModeHookReturnValue, "handlers" | "hoverHandlers"> {
/** {@inheritDoc TooltippedElementEventHandlers} */
handlers: Required<TooltippedElementEventHandlers<E>>;

Expand Down Expand Up @@ -334,41 +334,14 @@ export function useTooltip<E extends HTMLElement>({
const {
visible,
setVisible,
handlers: mouseHandlers,
handlers,
hoverHandlers: _hoverHandlers,
disableHoverMode,
clearHoverTimeout,
...others
} = useHoverMode<E>({
} = useHoverMode({
disabled,
onClick: (event) => {
onClick?.(event);
if (event.isPropagationStopped()) {
return;
}

setVisible(false);
setInitiatedBy(null);
window.clearTimeout(timeout.current);
},
onMouseEnter: (event) => {
onMouseEnter?.(event);
if (initiatedBy !== null) {
event.stopPropagation();
return;
}

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

setInitiatedBy(null);
},
exitVisibilityDelay: 0,
});
const hide = useCallback(() => {
window.clearTimeout(timeout.current);
Expand Down Expand Up @@ -530,12 +503,44 @@ export function useTooltip<E extends HTMLElement>({
});

const tooltipHandlers: Required<TooltippedElementEventHandlers<E>> = {
...mouseHandlers,
onFocus,
onBlur,
onKeyDown,
onTouchStart,
onContextMenu,
onClick(event) {
onClick?.(event);
if (event.isPropagationStopped()) {
return;
}

setVisible(false);
setInitiatedBy(null);
window.clearTimeout(timeout.current);
clearHoverTimeout();
},
onMouseEnter(event) {
onMouseEnter?.(event);
if (initiatedBy !== null) {
event.stopPropagation();
return;
}

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

setInitiatedBy(null);
handlers.onMouseLeave(event);
},
};

const tooltipId = `${baseId}-tooltip`;
Expand All @@ -562,5 +567,6 @@ export function useTooltip<E extends HTMLElement>({
elementProps,
tooltipProps,
disableHoverMode,
clearHoverTimeout,
};
}
Loading

0 comments on commit ac60bdb

Please sign in to comment.