Floating UI React DOM provides React hooks and utilities for positioning floating elements like tooltips, popovers, dropdowns, and menus. It wraps the core @floating-ui/dom functionality with React-specific optimizations, state management, and ref handling.
npm install @floating-ui/react-domreact >=16.8.0, react-dom >=16.8.0import { useFloating, offset, flip, shift, arrow } from '@floating-ui/react-dom';For CommonJS:
const { useFloating, offset, flip, shift, arrow } = require('@floating-ui/react-dom');import React, { useRef } from 'react';
import { useFloating, offset, flip, shift } from '@floating-ui/react-dom';
function Tooltip() {
const { refs, floatingStyles, isPositioned } = useFloating({
placement: 'top',
middleware: [
offset(10),
flip(),
shift({ padding: 8 })
]
});
return (
<>
<button ref={refs.setReference}>
Hover me
</button>
{isPositioned && (
<div
ref={refs.setFloating}
style={floatingStyles}
className="tooltip"
>
Tooltip content
</div>
)}
</>
);
}Floating UI React DOM is built around several key components:
The primary React hook for positioning floating elements relative to reference elements, with full React integration and automatic re-positioning.
function useFloating<RT extends ReferenceType = ReferenceType>(
options?: UseFloatingOptions<RT>
): UseFloatingReturn<RT>;
interface UseFloatingOptions<RT extends ReferenceType = ReferenceType> {
placement?: Placement;
strategy?: Strategy;
middleware?: Array<Middleware | null | undefined | false>;
platform?: Platform;
elements?: {
reference?: RT | null;
floating?: HTMLElement | null;
};
whileElementsMounted?: (
reference: RT,
floating: HTMLElement,
update: () => void
) => () => void;
open?: boolean;
transform?: boolean;
}
interface UseFloatingReturn<RT extends ReferenceType = ReferenceType> {
x: number;
y: number;
strategy: Strategy;
placement: Placement;
middlewareData: MiddlewareData;
isPositioned: boolean;
update: () => void;
floatingStyles: React.CSSProperties;
refs: {
reference: React.MutableRefObject<RT | null>;
floating: React.MutableRefObject<HTMLElement | null>;
setReference: (node: RT | null) => void;
setFloating: (node: HTMLElement | null) => void;
};
elements: {
reference: RT | null;
floating: HTMLElement | null;
};
}React-optimized middleware functions for controlling floating element behavior. Each middleware supports React dependency arrays for performance optimization.
function offset(options?: OffsetOptions, deps?: React.DependencyList): Middleware;
function flip(options?: FlipOptions, deps?: React.DependencyList): Middleware;
function shift(options?: ShiftOptions, deps?: React.DependencyList): Middleware;
function arrow(options: ArrowOptions, deps?: React.DependencyList): Middleware;Re-exported functions from @floating-ui/dom for direct use when needed.
function computePosition(
reference: ReferenceElement,
floating: FloatingElement,
config?: ComputePositionConfig
): Promise<ComputePositionReturn>;
function autoUpdate(
reference: ReferenceElement,
floating: FloatingElement,
update: () => void,
options?: AutoUpdateOptions
): () => void;
function detectOverflow(
state: MiddlewareState,
options?: DetectOverflowOptions
): SideObject;
function getOverflowAncestors(
node: Node,
list?: Array<Element | Window | VisualViewport>
): Array<Element | Window | VisualViewport>;
const platform: Platform;type ReferenceType = Element | VirtualElement;
interface UseFloatingData {
x: number;
y: number;
strategy: Strategy;
placement: Placement;
middlewareData: MiddlewareData;
isPositioned: boolean;
}
type Placement =
| 'top' | 'top-start' | 'top-end'
| 'right' | 'right-start' | 'right-end'
| 'bottom' | 'bottom-start' | 'bottom-end'
| 'left' | 'left-start' | 'left-end';
type Strategy = 'absolute' | 'fixed';
interface VirtualElement {
getBoundingClientRect(): ClientRectObject;
contextElement?: Element;
}
interface ClientRectObject {
x: number;
y: number;
width: number;
height: number;
top: number;
right: number;
bottom: number;
left: number;
}
interface MiddlewareData {
[key: string]: any;
arrow?: {
x?: number;
y?: number;
centerOffset: number;
};
autoPlacement?: {
index: number;
overflows: Array<{
placement: Placement;
overflows: number[];
}>;
};
flip?: {
index: number;
overflows: number[];
};
hide?: {
referenceHidden?: boolean;
escaped?: boolean;
referenceHiddenOffsets?: SideObject;
escapedOffsets?: SideObject;
};
offset?: Coords;
shift?: Coords;
size?: {
availableWidth: number;
availableHeight: number;
};
}
interface Coords {
x: number;
y: number;
}
interface SideObject {
top: number;
right: number;
bottom: number;
left: number;
}