Comprehensive focus management system for accessible floating elements with modal behavior, focus trapping, restoration, and ARIA compliance.
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>
)}
</>
);
}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>
);
}Controls the order in which elements receive focus:
'reference' - The reference element'floating' - The floating element container'content' - Content within the floating elementtype FocusOrder = Array<'reference' | 'floating' | 'content'>;Controls which element receives initial focus when the floating element opens:
type InitialFocus = number | React.MutableRefObject<HTMLElement | null>;Controls where focus returns when the floating element closes:
type ReturnFocus = boolean | React.MutableRefObject<HTMLElement | null>;<FloatingFocusManager
context={context}
modal={true}
guards={true}
returnFocus={true}
visuallyHiddenDismiss="Close dialog"
>
{/* Dialog content */}
</FloatingFocusManager><FloatingFocusManager
context={context}
modal={false}
closeOnFocusOut={true}
restoreFocus={false}
>
{/* Tooltip content */}
</FloatingFocusManager><FloatingFocusManager
context={context}
modal={false}
order={['floating', 'reference']}
initialFocus={0}
guards={false}
>
{/* Menu content */}
</FloatingFocusManager>Focus management automatically handles:
Built-in keyboard support: