Essential hooks for creating and positioning floating elements with collision detection, automatic updates, and context management.
Main hook that provides data to position a floating element and context for adding interactions.
/**
* Main hook for positioning floating elements
* @param options - Configuration options for positioning and behavior
* @returns Positioning data, context, and element refs
*/
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?: Element | null;
floating?: HTMLElement | null;
};
transform?: boolean;
whileElementsMounted?: (
reference: ReferenceType,
floating: HTMLElement,
update: () => void
) => void | (() => void);
open?: boolean;
onOpenChange?: (open: boolean, event?: Event, reason?: OpenChangeReason) => void;
nodeId?: string;
rootContext?: FloatingRootContext<RT>;
}
interface UseFloatingReturn<RT extends ReferenceType = ReferenceType> {
x: number;
y: number;
strategy: Strategy;
placement: Placement;
middlewareData: MiddlewareData;
isPositioned: boolean;
context: FloatingContext<RT>;
refs: ExtendedRefs<RT>;
elements: ExtendedElements<RT>;
floatingStyles: React.CSSProperties;
update(): void;
}Usage Examples:
import { useFloating, offset, flip, shift } from '@floating-ui/react';
import { useState } from 'react';
// Basic positioning
function BasicTooltip() {
const [isOpen, setIsOpen] = useState(false);
const { refs, floatingStyles, context } = useFloating({
placement: 'top',
open: isOpen,
onOpenChange: setIsOpen,
middleware: [offset(10), flip(), shift({ padding: 5 })],
});
return (
<>
<button ref={refs.setReference}>Reference</button>
{isOpen && (
<div ref={refs.setFloating} style={floatingStyles}>
Tooltip
</div>
)}
</>
);
}
// With external elements
function ExternalElements() {
const [referenceEl, setReferenceEl] = useState<HTMLElement | null>(null);
const [floatingEl, setFloatingEl] = useState<HTMLElement | null>(null);
const { floatingStyles } = useFloating({
elements: {
reference: referenceEl,
floating: floatingEl,
},
middleware: [offset(10)],
});
return (
<>
<button ref={setReferenceEl}>Reference</button>
<div ref={setFloatingEl} style={floatingStyles}>
Floating element
</div>
</>
);
}Creates a root context that can be shared between multiple floating UI hooks and components.
/**
* Creates a root context for floating UI state management
* @param options - Required context configuration
* @returns Root context for sharing between hooks
*/
function useFloatingRootContext(
options: UseFloatingRootContextOptions
): FloatingRootContext;
interface UseFloatingRootContextOptions {
open?: boolean;
onOpenChange?: (open: boolean, event?: Event, reason?: OpenChangeReason) => void;
elements: {
reference: Element | null;
floating: HTMLElement | null;
};
}Usage Example:
import { useFloatingRootContext, useClick, useInteractions } from '@floating-ui/react';
import { useState } from 'react';
function SharedContext() {
const [isOpen, setIsOpen] = useState(false);
const [referenceEl, setReferenceEl] = useState<HTMLElement | null>(null);
const [floatingEl, setFloatingEl] = useState<HTMLElement | null>(null);
const rootContext = useFloatingRootContext({
open: isOpen,
onOpenChange: setIsOpen,
elements: {
reference: referenceEl,
floating: floatingEl,
},
});
const click = useClick(rootContext);
const { getReferenceProps, getFloatingProps } = useInteractions([click]);
return (
<>
<button ref={setReferenceEl} {...getReferenceProps()}>
Trigger
</button>
{isOpen && (
<div ref={setFloatingEl} {...getFloatingProps()}>
Content
</div>
)}
</>
);
}Merges multiple refs into a single callback ref for component composition.
/**
* Merges an array of refs into a single memoized callback ref
* @param refs - Array of refs to merge, including undefined values
* @returns Single callback ref or null
*/
function useMergeRefs<Instance>(
refs: Array<React.Ref<Instance> | undefined>
): null | React.RefCallback<Instance>;Usage Example:
import { useMergeRefs } from '@floating-ui/react';
import { useRef, forwardRef } from 'react';
const MyComponent = forwardRef<HTMLDivElement, {}>((props, ref) => {
const internalRef = useRef<HTMLDivElement>(null);
const mergedRef = useMergeRefs([ref, internalRef]);
return <div ref={mergedRef} {...props} />;
});React 18's useId hook with fallback for earlier versions.
/**
* Uses React 18's built-in useId() when available, fallback for earlier versions
* @returns Unique string ID or undefined
*/
const useId: () => string | undefined;Usage Example:
import { useId } from '@floating-ui/react';
function LabeledInput() {
const id = useId();
return (
<>
<label htmlFor={id}>Input Label</label>
<input id={id} type="text" />
</>
);
}interface ExtendedRefs<RT> {
reference: React.MutableRefObject<ReferenceType | null>;
floating: React.MutableRefObject<HTMLElement | null>;
domReference: React.MutableRefObject<NarrowedElement<RT> | null>;
setReference(node: RT | null): void;
setFloating(node: HTMLElement | null): void;
setPositionReference(node: ReferenceType | null): void;
}
interface ExtendedElements<RT> {
reference: ReferenceType | null;
floating: HTMLElement | null;
domReference: NarrowedElement<RT> | null;
}
interface ContextData {
openEvent?: Event;
floatingContext?: FloatingContext;
typing?: boolean;
[key: string]: any;
}
interface FloatingEvents {
emit<T extends string>(event: T, data?: any): void;
on(event: string, handler: (data: any) => void): void;
off(event: string, handler: (data: any) => void): void;
}
type NarrowedElement<T> = T extends Element ? T : Element;