or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdmiddleware.md
tile.json

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;
}