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

focus-management.mddocs/

Focus Management

Comprehensive focus management system for accessible floating elements with modal behavior, focus trapping, restoration, and ARIA compliance.

Capabilities

FloatingFocusManager Component

Manages focus for accessible floating elements with modal behavior, focus trapping, and restoration.

/**
 * Focus management component for accessible floating elements
 * @param props - Focus management configuration
 * @returns React component providing focus management
 */
interface FloatingFocusManagerProps {
  children: React.JSX.Element;
  context: FloatingRootContext;
  disabled?: boolean;
  order?: Array<'reference' | 'floating' | 'content'>;
  initialFocus?: number | React.MutableRefObject<HTMLElement | null>;
  guards?: boolean;
  returnFocus?: boolean | React.MutableRefObject<HTMLElement | null>;
  restoreFocus?: boolean;
  modal?: boolean;
  visuallyHiddenDismiss?: boolean | string;
  closeOnFocusOut?: boolean;
  outsideElementsInert?: boolean;
  getInsideElements?: () => Element[];
}

declare const FloatingFocusManager: React.FC<FloatingFocusManagerProps>;

Usage Examples:

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

// Basic focus management
function Dialog() {
  const [isOpen, setIsOpen] = useState(false);

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

  const click = useClick(context);
  const { getReferenceProps, getFloatingProps } = useInteractions([click]);

  return (
    <>
      <button ref={refs.setReference} {...getReferenceProps()}>
        Open Dialog
      </button>
      {isOpen && (
        <FloatingFocusManager context={context} modal>
          <div
            ref={refs.setFloating}
            {...getFloatingProps()}
            style={{
              background: 'white',
              border: '1px solid black',
              padding: '1rem',
            }}
          >
            <p>Dialog content</p>
            <button onClick={() => setIsOpen(false)}>Close</button>
          </div>
        </FloatingFocusManager>
      )}
    </>
  );
}

// Custom focus order
function CustomFocusOrder() {
  const [isOpen, setIsOpen] = useState(false);
  const { refs, context } = useFloating({
    open: isOpen,
    onOpenChange: setIsOpen,
  });

  return (
    <>
      <button ref={refs.setReference}>Open</button>
      {isOpen && (
        <FloatingFocusManager 
          context={context}
          order={['floating', 'reference']}
          initialFocus={0}
          returnFocus={false}
        >
          <div ref={refs.setFloating}>
            <input placeholder="First input" />
            <input placeholder="Second input" />
            <button onClick={() => setIsOpen(false)}>Close</button>
          </div>
        </FloatingFocusManager>
      )}
    </>
  );
}

// Non-modal focus management
function NonModal() {
  const [isOpen, setIsOpen] = useState(false);
  const { refs, context } = useFloating({
    open: isOpen,
    onOpenChange: setIsOpen,
  });

  return (
    <>
      <button ref={refs.setReference}>Open Tooltip</button>
      {isOpen && (
        <FloatingFocusManager 
          context={context}
          modal={false}
          closeOnFocusOut
        >
          <div ref={refs.setFloating}>
            Interactive tooltip content
            <button>Action</button>
          </div>
        </FloatingFocusManager>
      )}
    </>
  );
}

FocusGuard Component

Internal utility component for creating focus trap boundaries.

/**
 * Internal component for focus trapping boundaries
 * @param props - Focus guard configuration
 * @returns Hidden element that traps focus
 */
interface FocusGuardProps {
  onFocus?: (event: React.FocusEvent) => void;
}

declare const FocusGuard: React.FC<FocusGuardProps>;

Usage Example:

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

// Typically used internally by FloatingFocusManager
function CustomFocusTrap() {
  return (
    <div>
      <FocusGuard onFocus={() => console.log('Focus trapped')} />
      <input placeholder="Content" />
      <button>Button</button>
      <FocusGuard onFocus={() => console.log('Focus trapped')} />
    </div>
  );
}

Focus Management Props

Order Configuration

Controls the order in which elements receive focus:

  • 'reference' - The reference element
  • 'floating' - The floating element container
  • 'content' - Content within the floating element
type FocusOrder = Array<'reference' | 'floating' | 'content'>;

Initial Focus Options

Controls which element receives initial focus when the floating element opens:

type InitialFocus = number | React.MutableRefObject<HTMLElement | null>;
  • Number: Index of focusable element to focus
  • Ref: Specific element to focus initially

Return Focus Options

Controls where focus returns when the floating element closes:

type ReturnFocus = boolean | React.MutableRefObject<HTMLElement | null>;
  • true: Return to previously focused element
  • false: Don't manage return focus
  • Ref: Return focus to specific element

Focus Management Patterns

Modal Dialogs

<FloatingFocusManager 
  context={context}
  modal={true}
  guards={true}
  returnFocus={true}
  visuallyHiddenDismiss="Close dialog"
>
  {/* Dialog content */}
</FloatingFocusManager>

Non-Modal Tooltips

<FloatingFocusManager 
  context={context}
  modal={false}
  closeOnFocusOut={true}
  restoreFocus={false}
>
  {/* Tooltip content */}
</FloatingFocusManager>

Dropdown Menus

<FloatingFocusManager 
  context={context}
  modal={false}
  order={['floating', 'reference']}
  initialFocus={0}
  guards={false}
>
  {/* Menu content */}
</FloatingFocusManager>

Accessibility Features

ARIA Support

Focus management automatically handles:

  • aria-hidden: Applied to background elements when modal
  • aria-describedby: Links reference to floating content
  • aria-expanded: Indicates expanded state on reference element
  • role: Applied based on useRole hook configuration

Keyboard Navigation

Built-in keyboard support:

  • Tab: Navigate through focusable elements
  • Shift+Tab: Navigate backwards through focusable elements
  • Escape: Close modal floating elements (if useDismiss is configured)

Screen Reader Support

  • Visually hidden dismiss button: Optional screen reader accessible close button
  • Focus announcements: Proper focus management for screen reader navigation
  • Element descriptions: ARIA descriptions for floating element relationships