React library for creating accessible floating UI elements like tooltips, popovers, and dropdowns with advanced positioning
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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;