Composable hooks for handling user interactions like clicks, hovers, focus, dismissal, and custom pointer events with floating elements.
Merges multiple interaction hooks' props into unified prop getters for composable behavior.
/**
* Merges interaction hooks' props into prop getters
* @param propsList - Array of ElementProps from interaction hooks
* @returns Prop getters for reference, floating, and item elements
*/
function useInteractions(
propsList?: Array<ElementProps | void>
): UseInteractionsReturn;
interface UseInteractionsReturn {
getReferenceProps: (userProps?: React.HTMLProps<Element>) => Record<string, unknown>;
getFloatingProps: (userProps?: React.HTMLProps<HTMLElement>) => Record<string, unknown>;
getItemProps: (userProps?: Omit<React.HTMLProps<HTMLElement>, 'selected' | 'active'> & ExtendedUserProps) => Record<string, unknown>;
}
interface ExtendedUserProps {
active?: boolean;
selected?: boolean;
}Usage Example:
import { useFloating, useInteractions, useClick, useHover, useDismiss } from '@floating-ui/react';
function MultiInteraction() {
const [isOpen, setIsOpen] = useState(false);
const { refs, floatingStyles, context } = useFloating({
open: isOpen,
onOpenChange: setIsOpen,
});
const click = useClick(context);
const hover = useHover(context);
const dismiss = useDismiss(context);
const { getReferenceProps, getFloatingProps } = useInteractions([
click,
hover,
dismiss,
]);
return (
<>
<button ref={refs.setReference} {...getReferenceProps()}>
Reference
</button>
{isOpen && (
<div ref={refs.setFloating} style={floatingStyles} {...getFloatingProps()}>
Floating content
</div>
)}
</>
);
}Opens or closes the floating element when clicking the reference element.
/**
* Handles click interactions for opening/closing floating elements
* @param context - Floating UI context
* @param props - Click behavior configuration
* @returns Element props for click handling
*/
function useClick(
context: FloatingRootContext,
props?: UseClickProps
): ElementProps;
interface UseClickProps {
enabled?: boolean;
event?: 'click' | 'mousedown';
toggle?: boolean;
ignoreMouse?: boolean;
keyboardHandlers?: boolean;
stickIfOpen?: boolean;
}Usage Examples:
import { useClick } from '@floating-ui/react';
// Basic click
const click = useClick(context);
// Click with options
const click = useClick(context, {
event: 'mousedown',
toggle: false,
keyboardHandlers: true,
});Opens the floating element while hovering over the reference element.
/**
* Handles hover interactions like CSS :hover
* @param context - Floating UI context
* @param props - Hover behavior configuration
* @returns Element props for hover handling
*/
function useHover(
context: FloatingRootContext,
props?: UseHoverProps
): ElementProps;
interface UseHoverProps {
enabled?: boolean;
handleClose?: HandleClose | null;
restMs?: number | (() => number);
delay?: Delay | (() => Delay);
mouseOnly?: boolean;
move?: boolean;
}
interface HandleClose {
(context: HandleCloseContext): (event: MouseEvent) => void;
__options?: SafePolygonOptions;
}
interface HandleCloseContext extends FloatingContext {
onClose: () => void;
tree?: FloatingTreeType | null;
leave?: boolean;
x?: number;
y?: number;
}Usage Examples:
import { useHover, safePolygon } from '@floating-ui/react';
// Basic hover
const hover = useHover(context);
// Hover with delay
const hover = useHover(context, {
delay: { open: 200, close: 100 },
});
// Hover with safe polygon
const hover = useHover(context, {
handleClose: safePolygon({
buffer: 2,
blockPointerEvents: true,
}),
});Opens the floating element while the reference element has focus.
/**
* Handles focus interactions like CSS :focus
* @param context - Floating UI context
* @param props - Focus behavior configuration
* @returns Element props for focus handling
*/
function useFocus(
context: FloatingRootContext,
props?: UseFocusProps
): ElementProps;
interface UseFocusProps {
enabled?: boolean;
visibleOnly?: boolean;
}Usage Example:
import { useFocus } from '@floating-ui/react';
// Focus on any focus (including programmatic)
const focus = useFocus(context);
// Focus only on visible focus (keyboard/mouse)
const focus = useFocus(context, {
visibleOnly: true,
});Closes the floating element when dismissal is requested (escape key, outside press, etc.).
/**
* Handles dismissal interactions (escape, outside press, etc.)
* @param context - Floating UI context
* @param props - Dismissal behavior configuration
* @returns Element props for dismissal handling
*/
function useDismiss(
context: FloatingRootContext,
props?: UseDismissProps
): ElementProps;
interface UseDismissProps {
enabled?: boolean;
escapeKey?: boolean;
referencePress?: boolean;
referencePressEvent?: 'pointerdown' | 'mousedown' | 'click';
outsidePress?: boolean | ((event: MouseEvent) => boolean);
outsidePressEvent?: 'pointerdown' | 'mousedown' | 'click';
ancestorScroll?: boolean;
bubbles?: boolean | {escapeKey?: boolean; outsidePress?: boolean};
capture?: boolean | {escapeKey?: boolean; outsidePress?: boolean};
}Usage Examples:
import { useDismiss } from '@floating-ui/react';
// Basic dismissal (escape + outside press)
const dismiss = useDismiss(context);
// Custom dismissal behavior
const dismiss = useDismiss(context, {
outsidePress: (event) => {
// Custom logic for outside press
return !event.target.closest('.allowed-area');
},
escapeKey: false,
ancestorScroll: true,
});Adds base screen reader props for accessibility based on the floating element's role.
/**
* Adds ARIA props for accessibility based on role
* @param context - Floating UI context
* @param props - Role configuration
* @returns Element props with ARIA attributes
*/
function useRole(
context: FloatingRootContext,
props?: UseRoleProps
): ElementProps;
interface UseRoleProps {
enabled?: boolean;
role?: AriaRole | ComponentRole;
}
type AriaRole = 'tooltip' | 'dialog' | 'alertdialog' | 'menu' | 'listbox' | 'grid' | 'tree';
type ComponentRole = 'select' | 'label' | 'combobox';Usage Examples:
import { useRole } from '@floating-ui/react';
// Tooltip role (default)
const role = useRole(context);
// Dialog role
const role = useRole(context, { role: 'dialog' });
// Menu role
const role = useRole(context, { role: 'menu' });Positions the floating element relative to a client point (mouse cursor by default).
/**
* Positions element relative to client point (e.g., mouse cursor)
* @param context - Floating UI context
* @param props - Client point configuration
* @returns Element props for client point positioning
*/
function useClientPoint(
context: FloatingRootContext,
props?: UseClientPointProps
): ElementProps;
interface UseClientPointProps {
enabled?: boolean;
axis?: 'x' | 'y' | 'both';
x?: number | null;
y?: number | null;
}Usage Examples:
import { useClientPoint } from '@floating-ui/react';
// Follow mouse cursor
const clientPoint = useClientPoint(context);
// Follow only x-axis
const clientPoint = useClientPoint(context, {
axis: 'x',
});
// Fixed position
const clientPoint = useClientPoint(context, {
x: 100,
y: 200,
});Creates a safe polygon area for hover interactions to prevent accidental closing.
/**
* Creates safe polygon area for hover interactions
* @param options - Polygon configuration
* @returns HandleClose function for useHover
*/
function safePolygon(options?: SafePolygonOptions): HandleClose;
interface SafePolygonOptions {
buffer?: number;
blockPointerEvents?: boolean;
requireIntent?: boolean;
}Usage Example:
import { useHover, safePolygon } from '@floating-ui/react';
const hover = useHover(context, {
handleClose: safePolygon({
buffer: 2,
blockPointerEvents: true,
requireIntent: true,
}),
});Handles typeahead functionality for lists, allowing users to type characters to find and navigate to list items.
/**
* Handles typeahead functionality for lists
* @param context - Floating UI context
* @param props - Typeahead configuration
* @returns Element props for typeahead handling
*/
function useTypeahead(
context: FloatingRootContext,
props: UseTypeaheadProps
): ElementProps;
interface UseTypeaheadProps {
listRef: React.MutableRefObject<Array<string | null>>;
activeIndex: number | null;
onMatch?: (index: number) => void;
onTypingChange?: (isTyping: boolean) => void;
enabled?: boolean;
findMatch?: null | ((list: Array<string | null>, typedString: string) => string | null | undefined);
resetMs?: number;
ignoreKeys?: Array<string>;
selectedIndex?: number | null;
}Merges multiple refs into a single callback ref for easier ref management.
/**
* Merges multiple refs into a single callback ref
* @param refs - Array of refs to merge
* @returns Single merged callback ref or null
*/
function useMergeRefs<Instance>(
refs: Array<React.Ref<Instance> | undefined>
): null | React.RefCallback<Instance>;Provides a unique ID that works with React 18's useId or falls back to a custom implementation.
/**
* Generates a unique ID using React 18's useId when available
* @returns Unique string ID or undefined during SSR
*/
function useId(): string | undefined;interface ElementProps {
reference?: React.HTMLProps<Element>;
floating?: React.HTMLProps<HTMLElement>;
item?: React.HTMLProps<HTMLElement> | ((props: ExtendedUserProps) => React.HTMLProps<HTMLElement>);
}
type Delay = number | Partial<{open: number; close: number}>;