or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-positioning.mdfocus-management.mdindex.mdinteraction-hooks.mdlayout-components.mdlist-navigation.mdpositioning-middleware.mdtransitions.mdtree-context.md
tile.json

core-positioning.mddocs/

Core Positioning

Essential hooks for creating and positioning floating elements with collision detection, automatic updates, and context management.

Capabilities

useFloating Hook

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

useFloatingRootContext Hook

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

useMergeRefs Hook

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

useId Hook

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" />
    </>
  );
}

Core Types

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;