useHoverMode
function useHoverMode(
options: ControlledHoverModeOptions | UncontrolledHoverModeOptions
): HoverModeImplementation;
The useHoverMode
hook is used to implement an immediate hover state after
hovering related elements for a short duration. The main use-case is for
showing tooltips immediately after hovering another tooltipped element.
This relies on creating a context provider using useHoverModeProvider to link related elements together.
Example Usage
See the useTooltip and TooltipHoverModeProvider for a real world example.
import { type MouseEvent } from "react";
import {
type CustomHoverContext,
useCustomHoverContext,
} from "./useCustomHoverContext.jsx";
interface CustomHoverModeImplementation {
onMouseEnter: <E extends HTMLElement>(event: MouseEvent<E>) => void;
onMouseLeave: <E extends HTMLElement>(event: MouseEvent<E>) => void;
}
function useCustomHoverMode(): CustomHoverModeImplementation {
const {
animatedOnceRef,
hoverTimeoutRef,
leaveTimeoutRef,
enableHoverMode,
disableHoverMode,
startDisableTimer,
clearDisableTimer,
} = useCustomHoverContext();
const {
visible,
setVisible,
startShowFlow,
startHideFlow,
clearVisibilityTimeout,
} = useHoverMode({
hoverTimeout,
hoverTimeoutRef,
leaveTimeout,
leaveTimeoutRef,
enableHoverMode,
disableHoverMode,
startDisableTimer,
clearDisableTimer,
});
return {
onMouseEnter(event) {
startShowFlow(event.currentTarget.id);
},
onMouseLeave(event) {
startHideFlow();
},
};
}
Parameters
options
- An object with the following definition:
export type HoverModeOptions =
| ControlledHoverModeOptions
| UncontrolledHoverModeOptions;
export interface ControlledHoverModeOptions
extends HoverModeConfigurationOptions {
setVisible: UseStateSetter<boolean>;
}
export interface UncontrolledHoverModeOptions
extends HoverModeConfigurationOptions {
defaultVisible?: UseStateInitializer<boolean>;
}
export interface HoverModeConfigurationOptions extends SimpleHoverModeContext {
/** @defaultValue `false` */
disabled?: boolean;
/**
* This can be used to override the `HoverModeContext`'s hover time.
*/
hoverTimeout?: number;
/**
* This can be used to override the `HoverModeContext`'s leave time.
*/
leaveTimeout?: number;
}
export interface SimpleHoverModeContext {
/**
* @example Main Usage
* ```ts
* onMouseEnter(event) {
* const hoverTimeout = hoverTimeoutRef.current;
* if (typeof hoverTimeout !== "number" || mode === "touch") {
* return;
* }
*
* const { id } = event.currentTarget;
* clearDisableTimer();
* window.clearTimeout(visibilityTimeout.current);
* visibilityTimeout.current = window.setTimeout(() => {
* enableHoverMode(id);
* setVisible(true);
* }, hoverTimeout);
* }
* ```
*/
hoverTimeoutRef: NonNullRef<number | undefined>;
/**
* @example Main Usage
* ```ts
* onMouseLeave() {
* if (mode === "touch") {
* return
* }
*
* startDisableTimer();
* window.clearTimeout(visibilityTimeout.current);
* visibilityTimeout.current = window.setTimeout(() => {
* setVisible(false)
* }, leaveTimeoutRef.current);
* }
* ```
*/
leaveTimeoutRef: NonNullRef<number>;
/**
* When this is called, the {@link hoverTimeoutRef} will be set to `0` and the
* {@link HoverModeContext.activeId} will be set to this `activeId` value.
*
* @see {@link hoverTimeoutRef} for an example.
*/
enableHoverMode: (activeId: string) => void;
/**
* Disables all hover mode behavior by clearing all timeouts and resetting
* internal state.
*/
disableHoverMode: () => void;
/**
* @see {@link leaveTimeoutRef} for an example.
*/
startDisableTimer: () => void;
/**
* @see {@link hoverTimeoutRef} for an example.
*/
clearDisableTimer: () => void;
}
Returns
An object with the following definition:
export interface HoverModeImplementation {
// `visible` and `setVisible` will be defined if the `setVisible` option was not provided
visible?: boolean;
setVisible?: UseStateSetter<boolean>;
startShowFlow: (id?: string | MouseEvent) => void;
startHideFlow: () => void;
clearVisibilityTimeout: () => void;
}