import { type CSSProperties, type FocusEvent, type MouseEvent, type Ref, type RefObject, type TouchEvent } from "react"; import { type ControlledHoverModeImplementation } from "../hoverMode/useHoverMode.js"; import { type UserInteractionMode } from "../interaction/UserInteractionModeProvider.js"; import { type SimplePosition } from "../positioning/types.js"; import { type FixedPositioningTransitionCallbacks } from "../positioning/useFixedPositioning.js"; import { type UseStateSetter } from "../types.js"; import { type TooltipPositionHookOptions } from "./useTooltipPosition.js"; /** @since 2.8.0 */ export interface TooltipPositioningOptions { style?: CSSProperties; /** * @see {@link FixedPositioningOptions.vwMargin} * @defaultValue `16` */ vwMargin?: number; /** * @see {@link FixedPositioningOptions.vhMargin} * @defaultValue `16` */ vhMargin?: number; /** * Set this to `true` to reduce the font size and padding on the tooltip and * the amount of spacing between the tooltipped element and the tooltip. * * @defaultValue `false` */ dense?: boolean; /** * The amount of spacing to use between the tooltipped element and the tooltip * when {@link disableAutoSpacing} is `false`. * * @defaultValue `"1.5rem` */ spacing?: number | string; /** * The amount of spacing to use between the tooltipped element and the tooltip * when {@link disableAutoSpacing} is `false` and {@link dense} is `true`. * * @defaultValue `"0.875rem` */ denseSpacing?: number | string; /** * Set this to `true` to prevent the {@link defaultPosition} to swap to the * other side of the tooltipped element when it is too close to the viewport * edge. This will always be `true` if a {@link position} is provided. * * @defaultValue `false` */ disableSwapping?: boolean; /** * @defaultValue `false` */ disableAutoSpacing?: boolean; } /** * @since 2.8.0 * @since 6.0.0 Removed the `TooltipTouchEventHandlers` and * `TooltipKeyboardEventHandlers` types, removed the need for the `onKeyDown` * event. */ export interface TooltippedElementEventHandlers { onBlur?: (event: FocusEvent) => void; onFocus?: (event: FocusEvent) => void; onMouseEnter?: (event: MouseEvent) => void; onMouseLeave?: (event: MouseEvent) => void; onTouchStart?: (event: TouchEvent) => void; onTouchEnd?: (event: TouchEvent) => void; onContextMenu?: (event: MouseEvent) => void; } /** * @since 2.8.0 * @since 6.0.0 Renamed from `TooltipHookProvidedElementProps` */ export interface ProvidedTooltippedElementProps extends Required> { "aria-describedby": string | undefined; id: string; } /** * @since 2.8.0 * @since 6.0.0 A major API change for the hover mode behavior and no longer * requires a `baseId`/`id` for the tooltip. Also renamed from * `TooltipHookOptions` to `TooltipOptions` to match other hook naming * conventions. */ export interface TooltipOptions extends FixedPositioningTransitionCallbacks, TooltippedElementEventHandlers, TooltipPositioningOptions, TooltipPositionHookOptions { /** * @defaultValue `"tooltip-" + useId()` */ id?: string; /** * An optional override for the `aria-describedby` */ describedBy?: string; /** * Any styles to be merged with the fixed positioning styles for the tooltip. */ style?: CSSProperties; /** * Boolean if the event handlers should no longer attempt to show a tooltip. This * should be set to `true` when your component might not have a tooltip associated * with it. * * @example Real World Example * ```tsx * // This is _almost_ the source code for the `TooltippedButton` provided by react-md * import { Button } from "@react-md/core/button/Button"; * import { Tooltip } from "@react-md/core/tooltip/Tooltip"; * import { useTooltip } from "@react-md/core/tooltip/useTooltip"; * import { type ReactElement, type ReactNode } from "react"; * * export interface TooltippedButtonProps extends ButtonProps { * tooltip?: ReactNode; * } * * export function TooltippedButton({ * id, * tooltip, * children, * onBlur, * onFocus, * onMouseEnter, * onMouseLeave, * onTouchStart, * onTouchEnd, * onContextMenu, * ...props * }: TooltippedButtonProps): ReactElement { * const { elementProps, tooltipProps } = useTooltip({ * id, * disabled: !tooltip, * onBlur, * onFocus, * onMouseEnter, * onMouseLeave, * onTouchStart, * onTouchEnd, * onContextMenu, * }); * * return ( * <> * * {tooltip} * * ); * } * ``` * * @defaultValue `false` * @since 5.1.0 */ disabled?: boolean; /** * The amount of time (in ms) to hover an element before the tooltip becomes * visible. * * The default value is really the current hover timeout from the * `TooltipHoverModeProvider`. * * @defaultValue `1000` */ hoverTimeout?: number; /** * The amount of time to wait before triggering the exit animation for the * tooltip. * * The default value is really the current leaveTimeout timeout from the * `TooltipHoverModeProvider`. * * @defaultValue `0` */ leaveTimeout?: number; /** * Set this to `true` to only allow the tooltip to become visible when the * `event .currentTarget` or `overflowRef` has text overflow. * * @defaultValue `false` * @since 6.0.0 */ overflowOnly?: boolean; /** * @see {@link FixedPositioningOptions.disabled} * @defaultValue `false` */ disableFixedPositioning?: boolean; } /** * @since 2.8.0 * @since 6.0.0 This was renamed from `TooltipHookProvidedTooltipProps` */ export interface ProvidedTooltipProps extends Required { id: string; ref: Ref; dense: boolean; style: CSSProperties | undefined; visible: boolean; position: SimplePosition; } /** * @since 2.8.0 * @since 6.0.0 No longer returns any properties from the hover mode provider * because of the major API change to hover mode.. Also renamed from * `TooltipHookReturnValue` to `TooltipImplementation` to match other hook * naming conventions. */ export interface TooltipImplementation extends ControlledHoverModeImplementation { visible: boolean; setVisible: UseStateSetter; animatedOnce: boolean; initiatedBy: RefObject; elementProps: ProvidedTooltippedElementProps; tooltipProps: ProvidedTooltipProps; /** * This is a wrapper around the {@link setVisible} behavior that will also * clear any pending timeouts. */ hideTooltip: () => void; /** * @since 6.0.0 */ overflowRef: RefObject; } /** * @example Simple Usage * ```tsx * import { Button } from "@react-md/core/button/Button"; * import { Tooltip } from "@react-md/core/tooltip/Tooltip"; * import { useTooltip } from "@react-md/core/tooltip/useTooltip"; * * function Example() { * const { elementProps, tooltipProps } = useTooltip(); * * return ( * <> * * * Tooltip Content * * * ); * } * ``` * * @example Overflow-only Tooltips * ```tsx * import { cssUtils } from "@react-md/core/cssUtils"; * import { Link, type LinkProps } from "@react-md/core/link/Link"; * import { Tooltip } from "@react-md/core/tooltip/Tooltip"; * import { useTooltip } from "@react-md/core/tooltip/useTooltip"; * import { type ReactElement } from "react"; * * function NavigationLink(props: LinkProps): ReactElement { * const { children, ...remaining } = props; * * // using the `overflowRef` is optional and will default to the * // `event.currentTarget` when `null` * const { overflowRef, elementProps, tooltipProps } = useOverflowTooltip({ * // just to pass any event handlers * ...remaining, * overflowOnly: true, * }); * * return ( * * * {children} * * * {children} * * * ); * } * * function Example(): ReactElement { * return ( *
* Home * * Super long text that will be truncated with ellipsis and * have a tooltip appear * *
* ); * } * ``` * * ## Inspecting Tooltip Styles * * Since tooltips will disappear on blur, mouseleave, etc, it is a bit hard to * inspect the tooltip styles. In dev mode, you can manually set the visibility * to `true` through the dev tools. * - find your tooltip implementation * - expand the Tooltip hook * - expand the HoverMode hook * - set the first boolean state to `true` * * The tooltip will now remain visible allowing you to find it within the * "Inspector" tab in the dev tools. * * @see {@link https://react-md.dev/components/tooltip | Tooltip Demos} * @since 2.8.0 * @since 6.0.0 Uses a separate `TooltipHoverModeProvider`. * * TODO: I need to fix the tooltip for click events and history changes since * the mouseleave event will not be correctly bubbled if hovering a child * element when the click or history update happens. this causes the tooltip to * stay visible */ export declare function useTooltip(options?: TooltipOptions): TooltipImplementation;