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

interaction-hooks.mddocs/

Interaction Hooks

Composable hooks for handling user interactions like clicks, hovers, focus, dismissal, and custom pointer events with floating elements.

Capabilities

useInteractions Hook

Merges multiple interaction hooks' props into unified prop getters for composable behavior.

/**
 * Merges interaction hooks' props into prop getters
 * @param propsList - Array of ElementProps from interaction hooks
 * @returns Prop getters for reference, floating, and item elements
 */
function useInteractions(
  propsList?: Array<ElementProps | void>
): UseInteractionsReturn;

interface UseInteractionsReturn {
  getReferenceProps: (userProps?: React.HTMLProps<Element>) => Record<string, unknown>;
  getFloatingProps: (userProps?: React.HTMLProps<HTMLElement>) => Record<string, unknown>;
  getItemProps: (userProps?: Omit<React.HTMLProps<HTMLElement>, 'selected' | 'active'> & ExtendedUserProps) => Record<string, unknown>;
}

interface ExtendedUserProps {
  active?: boolean;
  selected?: boolean;
}

Usage Example:

import { useFloating, useInteractions, useClick, useHover, useDismiss } from '@floating-ui/react';

function MultiInteraction() {
  const [isOpen, setIsOpen] = useState(false);

  const { refs, floatingStyles, context } = useFloating({
    open: isOpen,
    onOpenChange: setIsOpen,
  });

  const click = useClick(context);
  const hover = useHover(context);
  const dismiss = useDismiss(context);

  const { getReferenceProps, getFloatingProps } = useInteractions([
    click,
    hover,
    dismiss,
  ]);

  return (
    <>
      <button ref={refs.setReference} {...getReferenceProps()}>
        Reference
      </button>
      {isOpen && (
        <div ref={refs.setFloating} style={floatingStyles} {...getFloatingProps()}>
          Floating content
        </div>
      )}
    </>
  );
}

useClick Hook

Opens or closes the floating element when clicking the reference element.

/**
 * Handles click interactions for opening/closing floating elements
 * @param context - Floating UI context
 * @param props - Click behavior configuration
 * @returns Element props for click handling
 */
function useClick(
  context: FloatingRootContext,
  props?: UseClickProps
): ElementProps;

interface UseClickProps {
  enabled?: boolean;
  event?: 'click' | 'mousedown';
  toggle?: boolean;
  ignoreMouse?: boolean;
  keyboardHandlers?: boolean;
  stickIfOpen?: boolean;
}

Usage Examples:

import { useClick } from '@floating-ui/react';

// Basic click
const click = useClick(context);

// Click with options
const click = useClick(context, {
  event: 'mousedown',
  toggle: false,
  keyboardHandlers: true,
});

useHover Hook

Opens the floating element while hovering over the reference element.

/**
 * Handles hover interactions like CSS :hover
 * @param context - Floating UI context  
 * @param props - Hover behavior configuration
 * @returns Element props for hover handling
 */
function useHover(
  context: FloatingRootContext,
  props?: UseHoverProps
): ElementProps;

interface UseHoverProps {
  enabled?: boolean;
  handleClose?: HandleClose | null;
  restMs?: number | (() => number);
  delay?: Delay | (() => Delay);
  mouseOnly?: boolean;
  move?: boolean;
}

interface HandleClose {
  (context: HandleCloseContext): (event: MouseEvent) => void;
  __options?: SafePolygonOptions;
}

interface HandleCloseContext extends FloatingContext {
  onClose: () => void;
  tree?: FloatingTreeType | null;
  leave?: boolean;
  x?: number;
  y?: number;
}

Usage Examples:

import { useHover, safePolygon } from '@floating-ui/react';

// Basic hover
const hover = useHover(context);

// Hover with delay
const hover = useHover(context, {
  delay: { open: 200, close: 100 },
});

// Hover with safe polygon
const hover = useHover(context, {
  handleClose: safePolygon({
    buffer: 2,
    blockPointerEvents: true,
  }),
});

useFocus Hook

Opens the floating element while the reference element has focus.

/**
 * Handles focus interactions like CSS :focus
 * @param context - Floating UI context
 * @param props - Focus behavior configuration  
 * @returns Element props for focus handling
 */
function useFocus(
  context: FloatingRootContext,
  props?: UseFocusProps
): ElementProps;

interface UseFocusProps {
  enabled?: boolean;
  visibleOnly?: boolean;
}

Usage Example:

import { useFocus } from '@floating-ui/react';

// Focus on any focus (including programmatic)
const focus = useFocus(context);

// Focus only on visible focus (keyboard/mouse)  
const focus = useFocus(context, {
  visibleOnly: true,
});

useDismiss Hook

Closes the floating element when dismissal is requested (escape key, outside press, etc.).

/**
 * Handles dismissal interactions (escape, outside press, etc.)
 * @param context - Floating UI context
 * @param props - Dismissal behavior configuration
 * @returns Element props for dismissal handling
 */
function useDismiss(
  context: FloatingRootContext,
  props?: UseDismissProps
): ElementProps;

interface UseDismissProps {
  enabled?: boolean;
  escapeKey?: boolean;
  referencePress?: boolean;
  referencePressEvent?: 'pointerdown' | 'mousedown' | 'click';
  outsidePress?: boolean | ((event: MouseEvent) => boolean);
  outsidePressEvent?: 'pointerdown' | 'mousedown' | 'click';
  ancestorScroll?: boolean;
  bubbles?: boolean | {escapeKey?: boolean; outsidePress?: boolean};
  capture?: boolean | {escapeKey?: boolean; outsidePress?: boolean};
}

Usage Examples:

import { useDismiss } from '@floating-ui/react';

// Basic dismissal (escape + outside press)
const dismiss = useDismiss(context);

// Custom dismissal behavior
const dismiss = useDismiss(context, {
  outsidePress: (event) => {
    // Custom logic for outside press
    return !event.target.closest('.allowed-area');
  },
  escapeKey: false,
  ancestorScroll: true,
});

useRole Hook

Adds base screen reader props for accessibility based on the floating element's role.

/**
 * Adds ARIA props for accessibility based on role
 * @param context - Floating UI context
 * @param props - Role configuration
 * @returns Element props with ARIA attributes
 */
function useRole(
  context: FloatingRootContext,
  props?: UseRoleProps
): ElementProps;

interface UseRoleProps {
  enabled?: boolean;
  role?: AriaRole | ComponentRole;
}

type AriaRole = 'tooltip' | 'dialog' | 'alertdialog' | 'menu' | 'listbox' | 'grid' | 'tree';
type ComponentRole = 'select' | 'label' | 'combobox';

Usage Examples:

import { useRole } from '@floating-ui/react';

// Tooltip role (default)
const role = useRole(context);

// Dialog role
const role = useRole(context, { role: 'dialog' });

// Menu role
const role = useRole(context, { role: 'menu' });

useClientPoint Hook

Positions the floating element relative to a client point (mouse cursor by default).

/**
 * Positions element relative to client point (e.g., mouse cursor)
 * @param context - Floating UI context
 * @param props - Client point configuration
 * @returns Element props for client point positioning
 */
function useClientPoint(
  context: FloatingRootContext,
  props?: UseClientPointProps
): ElementProps;

interface UseClientPointProps {
  enabled?: boolean;
  axis?: 'x' | 'y' | 'both';
  x?: number | null;
  y?: number | null;
}

Usage Examples:

import { useClientPoint } from '@floating-ui/react';

// Follow mouse cursor
const clientPoint = useClientPoint(context);

// Follow only x-axis
const clientPoint = useClientPoint(context, {
  axis: 'x',
});

// Fixed position
const clientPoint = useClientPoint(context, {
  x: 100,
  y: 200,
});

Utility Functions

safePolygon Function

Creates a safe polygon area for hover interactions to prevent accidental closing.

/**
 * Creates safe polygon area for hover interactions
 * @param options - Polygon configuration
 * @returns HandleClose function for useHover
 */
function safePolygon(options?: SafePolygonOptions): HandleClose;

interface SafePolygonOptions {
  buffer?: number;
  blockPointerEvents?: boolean;
  requireIntent?: boolean;
}

Usage Example:

import { useHover, safePolygon } from '@floating-ui/react';

const hover = useHover(context, {
  handleClose: safePolygon({
    buffer: 2,
    blockPointerEvents: true,
    requireIntent: true,
  }),
});

useTypeahead Hook

Handles typeahead functionality for lists, allowing users to type characters to find and navigate to list items.

/**
 * Handles typeahead functionality for lists
 * @param context - Floating UI context
 * @param props - Typeahead configuration
 * @returns Element props for typeahead handling
 */
function useTypeahead(
  context: FloatingRootContext,
  props: UseTypeaheadProps
): ElementProps;

interface UseTypeaheadProps {
  listRef: React.MutableRefObject<Array<string | null>>;
  activeIndex: number | null;
  onMatch?: (index: number) => void;
  onTypingChange?: (isTyping: boolean) => void;
  enabled?: boolean;
  findMatch?: null | ((list: Array<string | null>, typedString: string) => string | null | undefined);
  resetMs?: number;
  ignoreKeys?: Array<string>;
  selectedIndex?: number | null;
}

useMergeRefs Hook

Merges multiple refs into a single callback ref for easier ref management.

/**
 * Merges multiple refs into a single callback ref
 * @param refs - Array of refs to merge
 * @returns Single merged callback ref or null
 */
function useMergeRefs<Instance>(
  refs: Array<React.Ref<Instance> | undefined>
): null | React.RefCallback<Instance>;

useId Hook

Provides a unique ID that works with React 18's useId or falls back to a custom implementation.

/**
 * Generates a unique ID using React 18's useId when available
 * @returns Unique string ID or undefined during SSR
 */
function useId(): string | undefined;

Common Types

interface ElementProps {
  reference?: React.HTMLProps<Element>;
  floating?: React.HTMLProps<HTMLElement>;
  item?: React.HTMLProps<HTMLElement> | ((props: ExtendedUserProps) => React.HTMLProps<HTMLElement>);
}

type Delay = number | Partial<{open: number; close: number}>;