Platform-agnostic core positioning engine for floating UI elements like tooltips, popovers, and dropdowns.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core positioning functionality providing the main computePosition function for calculating optimal floating element coordinates.
Main function that computes x and y coordinates for positioning floating elements relative to reference elements.
/**
* Computes the x and y coordinates that will place the floating element
* next to a given reference element.
* This export does not have any platform interface logic. You will need to
* write one for the platform you are using Floating UI with.
*
* @param reference - The reference element
* @param floating - The floating element
* @param config - Configuration object
* @returns Promise resolving to positioning result
*/
function computePosition(
reference: unknown,
floating: unknown,
config: ComputePositionConfig
): Promise<ComputePositionReturn>;
interface ComputePositionConfig {
/** Object to interface with the current platform (required) */
platform: Platform;
/** Where to place the floating element relative to the reference element */
placement?: Placement;
/** The strategy to use when positioning the floating element */
strategy?: Strategy;
/** Array of middleware objects to modify positioning or provide data */
middleware?: Array<Middleware | null | undefined | false>;
}
interface ComputePositionReturn {
/** Final x coordinate for the floating element */
x: number;
/** Final y coordinate for the floating element */
y: number;
/** The final chosen placement of the floating element */
placement: Placement;
/** The strategy used to position the floating element */
strategy: Strategy;
/** Object containing data returned from all middleware, keyed by their name */
middlewareData: MiddlewareData;
}Usage Examples:
import { computePosition, offset, flip } from "@floating-ui/core";
// Basic positioning
const result = await computePosition(button, tooltip, {
placement: "top",
platform: domPlatform
});
// With middleware
const result = await computePosition(button, dropdown, {
placement: "bottom-start",
strategy: "absolute",
middleware: [
offset(10),
flip(),
shift({ padding: 8 })
],
platform: domPlatform
});
// Access computed values
console.log(`Position: ${result.x}, ${result.y}`);
console.log(`Final placement: ${result.placement}`);
console.log(`Middleware data:`, result.middlewareData);Required platform interface for DOM operations. Must be implemented for each platform (DOM, React Native, etc.). The first three methods are required; all others are optional but may be needed for advanced features.
interface Platform {
/** Get element rectangles (required) */
getElementRects(args: {
reference: ReferenceElement;
floating: FloatingElement;
strategy: Strategy;
}): Promise<ElementRects> | ElementRects;
/** Get clipping rectangle (required) */
getClippingRect(args: {
element: any;
boundary: Boundary;
rootBoundary: RootBoundary;
strategy: Strategy;
}): Promise<Rect> | Rect;
/** Get element dimensions (required) */
getDimensions(element: any): Promise<Dimensions> | Dimensions;
/** Convert offset parent relative rect to viewport relative (optional) */
convertOffsetParentRelativeRectToViewportRelativeRect?(args: {
elements?: Elements;
rect: Rect;
offsetParent: any;
strategy: Strategy;
}): Promise<Rect> | Rect;
/** Get offset parent element (optional) */
getOffsetParent?(element: any): Promise<any> | any;
/** Check if value is an element (optional) */
isElement?(value: any): Promise<boolean> | boolean;
/** Get document element (optional) */
getDocumentElement?(element: any): Promise<any> | any;
/** Get client rectangles for inline elements (optional) */
getClientRects?(element: any): Promise<Array<ClientRectObject>> | Array<ClientRectObject>;
/** Check if element uses RTL direction (optional) */
isRTL?(element: any): Promise<boolean> | boolean;
/** Get element scale factors (optional) */
getScale?(element: any): Promise<{x: number; y: number}> | {x: number; y: number};
}Interface for creating custom middleware that can modify positioning behavior.
interface Middleware {
/** Unique name for the middleware */
name: string;
/** Options passed to the middleware */
options?: any;
/** Function that performs the middleware logic */
fn: (state: MiddlewareState) => Promise<MiddlewareReturn> | MiddlewareReturn;
}
interface MiddlewareState {
/** Current x coordinate */
x: number;
/** Current y coordinate */
y: number;
/** Initial placement before middleware modifications */
initialPlacement: Placement;
/** Current placement (may be modified by middleware) */
placement: Placement;
/** Positioning strategy */
strategy: Strategy;
/** Data from previously executed middleware */
middlewareData: MiddlewareData;
/** Reference and floating elements */
elements: Elements;
/** Element rectangles */
rects: ElementRects;
/** Platform interface */
platform: Platform;
}
interface MiddlewareReturn {
/** New x coordinate (optional) */
x?: number;
/** New y coordinate (optional) */
y?: number;
/** Data to store in middlewareData (optional) */
data?: { [key: string]: any };
/** Reset positioning with new placement or rects (optional) */
reset?: boolean | {
placement?: Placement;
rects?: boolean | ElementRects;
};
}
interface MiddlewareData {
[key: string]: any;
arrow?: Partial<Coords> & { centerOffset: number; alignmentOffset?: number };
autoPlacement?: { index?: number; overflows: Array<{ placement: Placement; overflows: Array<number> }> };
flip?: { index?: number; overflows: Array<{ placement: Placement; overflows: Array<number> }> };
hide?: { referenceHidden?: boolean; escaped?: boolean; referenceHiddenOffsets?: SideObject; escapedOffsets?: SideObject };
offset?: Coords & { placement: Placement };
shift?: Coords & { enabled: { [key in Axis]: boolean } };
}Custom Middleware Example:
// Custom middleware that adds a random offset
const randomOffset = (): Middleware => ({
name: "randomOffset",
fn({ x, y }) {
return {
x: x + Math.random() * 10 - 5,
y: y + Math.random() * 10 - 5,
data: { randomApplied: true }
};
}
});
// Use in computePosition
const result = await computePosition(reference, floating, {
middleware: [randomOffset()],
platform: domPlatform
});// Element types
type ReferenceElement = any;
type FloatingElement = any;
interface Elements {
reference: ReferenceElement;
floating: FloatingElement;
}
// Boundary types
type Boundary = any;
type RootBoundary = "viewport" | "document" | Rect;
type ElementContext = "reference" | "floating";
// Function option type
type Derivable<T> = (state: MiddlewareState) => T;