CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-floating-ui--react-dom

React DOM bindings for Floating UI, enabling positioning of floating elements like tooltips, popovers, and dropdowns

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

middleware.mddocs/

Positioning Middleware

React-optimized positioning middleware for controlling floating element behavior. Each middleware function wraps the core @floating-ui/dom functionality with React dependency tracking for optimal performance, preventing unnecessary recalculations when dependencies haven't changed.

Common Types

type Derivable<T> = T | ((state: MiddlewareState) => T);

interface MiddlewareState {
  x: number;
  y: number;
  initialPlacement: Placement;
  placement: Placement;
  strategy: Strategy;
  middlewareData: MiddlewareData;
  rects: ElementRects;
  elements: Elements;
}

Capabilities

Offset Middleware

Translates the floating element along specified axes to create space between reference and floating elements.

/**
 * Modifies the placement by translating the floating element along the specified axes
 * @param options - Offset configuration or number (shorthand for mainAxis, can be derivable/function)
 * @param deps - React dependency list for optimization
 * @returns Middleware function
 */
function offset(
  options?: OffsetOptions | number | Derivable<OffsetOptions>,
  deps?: React.DependencyList
): Middleware;

interface OffsetOptions {
  mainAxis?: number;
  crossAxis?: number;
  alignmentAxis?: number | null;
}

Usage Examples:

import { useFloating, offset } from '@floating-ui/react-dom';

// Simple offset
const { refs, floatingStyles } = useFloating({
  middleware: [offset(10)] // 10px offset along main axis
});

// Complex offset
const { refs, floatingStyles } = useFloating({
  middleware: [
    offset({
      mainAxis: 10,    // Distance along placement axis
      crossAxis: 5,    // Distance perpendicular to placement
      alignmentAxis: 0 // Distance along alignment axis
    })
  ]
});

// Dynamic offset with dependencies
const [distance, setDistance] = useState(10);
const { refs, floatingStyles } = useFloating({
  middleware: [offset(distance, [distance])]
});

Shift Middleware

Keeps the floating element in view by shifting it when it would overflow the clipping boundary.

/**
 * Optimizes visibility by shifting the floating element to stay in view
 * @param options - Shift configuration options (can be derivable/function)
 * @param deps - React dependency list for optimization  
 * @returns Middleware function
 */
function shift(
  options?: ShiftOptions | Derivable<ShiftOptions>,
  deps?: React.DependencyList
): Middleware;

interface ShiftOptions {
  mainAxis?: boolean;
  crossAxis?: boolean;
  limiter?: {
    fn: (state: MiddlewareState) => Coords;
    options?: any;
  };
  boundary?: Boundary;
  rootBoundary?: RootBoundary;
  elementContext?: ElementContext;
  altBoundary?: boolean;
  padding?: Padding;
}

type Boundary = 'clippingAncestors' | Element | Array<Element> | Rect;
type RootBoundary = 'viewport' | 'document' | Rect;
type ElementContext = 'reference' | 'floating';
type Padding = number | Partial<SideObject>;

Usage Examples:

import { useFloating, shift, limitShift } from '@floating-ui/react-dom';

// Basic shift
const { refs, floatingStyles } = useFloating({
  middleware: [shift()]
});

// Shift with padding
const { refs, floatingStyles } = useFloating({
  middleware: [
    shift({ 
      padding: 8 // 8px padding from viewport edges
    })
  ]
});

// Shift with limiter
const { refs, floatingStyles } = useFloating({
  middleware: [
    shift({
      limiter: limitShift({
        offset: 25 // Stop shifting after 25px
      })
    })
  ]
});

// Cross-axis shifting
const { refs, floatingStyles } = useFloating({
  middleware: [
    shift({
      crossAxis: true, // Allow shifting perpendicular to placement
      boundary: document.querySelector('#container')
    })
  ]
});

Flip Middleware

Changes the placement of the floating element to keep it in view when the preferred placement would cause overflow.

/**
 * Optimizes visibility by flipping placement to avoid overflow
 * @param options - Flip configuration options (can be derivable/function)
 * @param deps - React dependency list for optimization
 * @returns Middleware function  
 */
function flip(
  options?: FlipOptions | Derivable<FlipOptions>,
  deps?: React.DependencyList
): Middleware;

interface FlipOptions {
  mainAxis?: boolean;
  crossAxis?: boolean;
  fallbackPlacements?: Array<Placement>;
  fallbackStrategy?: 'bestFit' | 'initialPlacement';
  fallbackAxisSideDirection?: 'none' | 'start' | 'end';
  flipAlignment?: boolean;
  boundary?: Boundary;
  rootBoundary?: RootBoundary;
  elementContext?: ElementContext;
  altBoundary?: boolean;
  padding?: Padding;
}

Usage Examples:

import { useFloating, flip } from '@floating-ui/react-dom';

// Basic flip
const { refs, floatingStyles } = useFloating({
  placement: 'top',
  middleware: [flip()] // Will flip to bottom if top overflows
});

// Custom fallback placements
const { refs, floatingStyles } = useFloating({
  placement: 'top',
  middleware: [
    flip({
      fallbackPlacements: ['top-start', 'top-end', 'bottom', 'right']
    })
  ]
});

// Flip with boundary
const { refs, floatingStyles } = useFloating({
  middleware: [
    flip({
      boundary: document.querySelector('#scroll-container'),
      padding: 8
    })
  ]
});

Arrow Middleware

Positions an arrow element to point from the floating element to the reference element.

/**
 * Positions an arrow element centered to the reference element
 * @param options - Arrow configuration with element ref or DOM element (can be derivable/function)
 * @param deps - React dependency list for optimization
 * @returns Middleware function
 */
function arrow(
  options: ArrowOptions | Derivable<ArrowOptions>,
  deps?: React.DependencyList
): Middleware;

interface ArrowOptions {
  element: React.MutableRefObject<Element | null> | Element | null;
  padding?: Padding;
}

Usage Examples:

import React, { useRef } from 'react';
import { useFloating, arrow, offset } from '@floating-ui/react-dom';

function TooltipWithArrow() {
  const arrowRef = useRef<HTMLDivElement>(null);
  
  const { refs, floatingStyles, middlewareData } = useFloating({
    placement: 'top',
    middleware: [
      offset(8),
      arrow({ element: arrowRef, padding: 4 })
    ]
  });

  const arrowX = middlewareData.arrow?.x;
  const arrowY = middlewareData.arrow?.y;

  return (
    <>
      <button ref={refs.setReference}>Reference</button>
      <div ref={refs.setFloating} style={floatingStyles}>
        Tooltip content
        <div
          ref={arrowRef}
          style={{
            position: 'absolute',
            left: arrowX != null ? `${arrowX}px` : '',
            top: arrowY != null ? `${arrowY}px` : '',
            width: '8px',
            height: '8px',
            backgroundColor: 'inherit',
            transform: 'rotate(45deg)'
          }}
        />
      </div>
    </>
  );
}

Size Middleware

Provides data to change the size of the floating element, such as preventing overflow or matching reference width.

/**
 * Provides data to change floating element size based on available space
 * @param options - Size configuration with apply function (can be derivable/function)
 * @param deps - React dependency list for optimization
 * @returns Middleware function
 */
function size(
  options?: SizeOptions | Derivable<SizeOptions>,
  deps?: React.DependencyList
): Middleware;

interface SizeOptions {
  apply?: (args: {
    availableWidth: number;
    availableHeight: number;
    elements: Elements;
    rects: ElementRects;
  }) => void | Promise<void>;
  boundary?: Boundary;
  rootBoundary?: RootBoundary;
  elementContext?: ElementContext;
  altBoundary?: boolean;
  padding?: Padding;
}

interface Elements {
  reference: Element;
  floating: HTMLElement;
}

interface ElementRects {
  reference: Rect;
  floating: Rect;
}

interface Rect {
  x: number;
  y: number;
  width: number;
  height: number;
}

Usage Examples:

import { useFloating, size } from '@floating-ui/react-dom';

// Constrain height to available space
const { refs, floatingStyles } = useFloating({
  middleware: [
    size({
      apply({ availableHeight, elements }) {
        Object.assign(elements.floating.style, {
          maxHeight: `${availableHeight}px`,
          overflow: 'auto'
        });
      }
    })
  ]
});

// Match reference element width
const { refs, floatingStyles } = useFloating({
  middleware: [
    size({
      apply({ rects, elements }) {
        Object.assign(elements.floating.style, {
          width: `${rects.reference.width}px`
        });
      }
    })
  ]
});

Hide Middleware

Provides data to hide the floating element when it's not in the same clipping context as the reference element.

/**
 * Provides data to hide floating element in applicable situations
 * @param options - Hide configuration options (can be derivable/function)
 * @param deps - React dependency list for optimization
 * @returns Middleware function
 */
function hide(
  options?: HideOptions | Derivable<HideOptions>,
  deps?: React.DependencyList
): Middleware;

interface HideOptions {
  strategy?: 'referenceHidden' | 'escaped';
  boundary?: Boundary;
  rootBoundary?: RootBoundary;
  elementContext?: ElementContext;
  altBoundary?: boolean;
  padding?: Padding;
}

Auto Placement Middleware

Automatically chooses the placement with the most available space, alternative to flip middleware.

/**
 * Optimizes visibility by choosing placement with most available space
 * @param options - Auto placement configuration (can be derivable/function)
 * @param deps - React dependency list for optimization
 * @returns Middleware function
 */
function autoPlacement(
  options?: AutoPlacementOptions | Derivable<AutoPlacementOptions>,
  deps?: React.DependencyList
): Middleware;

interface AutoPlacementOptions {
  crossAxis?: boolean;
  alignment?: Alignment | null;
  allowedPlacements?: Array<Placement>;
  autoAlignment?: boolean;
  boundary?: Boundary;
  rootBoundary?: RootBoundary;
  elementContext?: ElementContext;
  altBoundary?: boolean;
  padding?: Padding;
}

type Alignment = 'start' | 'end';

Inline Middleware

Provides improved positioning for inline reference elements that span multiple lines.

/**
 * Improves positioning for inline reference elements spanning multiple lines
 * @param options - Inline configuration options (can be derivable/function)
 * @param deps - React dependency list for optimization
 * @returns Middleware function
 */
function inline(
  options?: InlineOptions | Derivable<InlineOptions>,
  deps?: React.DependencyList
): Middleware;

interface InlineOptions {
  x?: number;
  y?: number;
  padding?: Padding;
}

Limit Shift Helper

Built-in limiter function that stops shift middleware at a certain point. Returns a limiter object designed to be used with the shift middleware's limiter option.

/**
 * Built-in limiter that stops shift() at a certain point
 * @param options - Limit shift configuration (can be derivable/function)
 * @param deps - React dependency list for optimization
 * @returns Limiter object with fn and options properties for use with shift middleware
 */
function limitShift(
  options?: LimitShiftOptions | Derivable<LimitShiftOptions>,
  deps?: React.DependencyList
): {
  fn: (state: MiddlewareState) => Coords;
  options: any;
};

interface LimitShiftOptions {
  offset?: number | ((args: { placement: Placement; rects: ElementRects }) => number) | {
    mainAxis?: number;
    crossAxis?: number;
  };
  mainAxis?: boolean;
  crossAxis?: boolean;
}

docs

index.md

middleware.md

tile.json