React library for creating accessible floating UI elements like tooltips, popovers, and dropdowns with advanced positioning
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
System for creating accessible lists, menus, and composite widgets with keyboard navigation, virtual focus, type-ahead search, and proper ARIA support.
Provides arrow key navigation for lists of items with real or virtual focus management.
/**
* Arrow key navigation for lists with real or virtual focus
* @param context - Floating UI context
* @param props - List navigation configuration
* @returns Element props for list navigation handling
*/
function useListNavigation(
context: FloatingRootContext,
props: UseListNavigationProps
): ElementProps;
interface UseListNavigationProps {
listRef: React.MutableRefObject<Array<HTMLElement | null>>;
activeIndex: number | null;
onNavigate?: (activeIndex: number | null) => void;
enabled?: boolean;
orientation?: 'vertical' | 'horizontal' | 'both';
loop?: boolean;
nested?: boolean;
focusItemOnOpen?: boolean | 'auto';
focusItemOnHover?: boolean;
cols?: number;
disabledIndices?: Array<number>;
allowEscape?: boolean;
itemSizes?: Array<number>;
dense?: boolean;
rtl?: boolean;
virtual?: boolean;
virtualItemRef?: React.MutableRefObject<HTMLElement | null>;
}Usage Examples:
import {
useListNavigation,
useFloating,
useClick,
useInteractions,
FloatingList,
useListItem
} from '@floating-ui/react';
import { useState, useRef } from 'react';
// Basic list navigation
function Menu() {
const [isOpen, setIsOpen] = useState(false);
const [activeIndex, setActiveIndex] = useState<number | null>(null);
const listRef = useRef<Array<HTMLElement | null>>([]);
const { refs, floatingStyles, context } = useFloating({
open: isOpen,
onOpenChange: setIsOpen,
});
const click = useClick(context);
const listNavigation = useListNavigation(context, {
listRef,
activeIndex,
onNavigate: setActiveIndex,
});
const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([
click,
listNavigation,
]);
const items = ['Item 1', 'Item 2', 'Item 3'];
return (
<>
<button ref={refs.setReference} {...getReferenceProps()}>
Menu
</button>
{isOpen && (
<FloatingList elementsRef={listRef} labelsRef={undefined}>
<div
ref={refs.setFloating}
style={floatingStyles}
{...getFloatingProps()}
>
{items.map((item, index) => (
<MenuItem
key={item}
label={item}
active={activeIndex === index}
{...getItemProps({
onClick() {
setIsOpen(false);
},
})}
/>
))}
</div>
</FloatingList>
)}
</>
);
}
function MenuItem(props: {
label: string;
active: boolean;
[key: string]: any;
}) {
const { label, active, ...rest } = props;
const { ref, index } = useListItem({ label });
return (
<div
ref={ref}
role="menuitem"
tabIndex={active ? 0 : -1}
style={{
background: active ? 'lightblue' : 'white',
padding: '8px',
}}
{...rest}
>
{label}
</div>
);
}
// Grid navigation
function GridMenu() {
const [activeIndex, setActiveIndex] = useState(0);
const listRef = useRef<Array<HTMLElement | null>>([]);
const { refs, context } = useFloating({
open: true,
onOpenChange: () => {},
});
const listNavigation = useListNavigation(context, {
listRef,
activeIndex,
onNavigate: setActiveIndex,
orientation: 'both',
cols: 3,
loop: true,
});
const { getFloatingProps, getItemProps } = useInteractions([listNavigation]);
const items = Array.from({ length: 9 }, (_, i) => `Item ${i + 1}`);
return (
<div
ref={refs.setFloating}
style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)' }}
{...getFloatingProps()}
>
{items.map((item, index) => (
<div
key={item}
ref={(el) => { listRef.current[index] = el; }}
tabIndex={activeIndex === index ? 0 : -1}
style={{
background: activeIndex === index ? 'lightblue' : 'white',
padding: '8px',
border: '1px solid gray',
}}
{...getItemProps()}
>
{item}
</div>
))}
</div>
);
}Provides type-to-search functionality for focusing items in lists by typing their labels.
/**
* Type-to-search functionality for focusing items
* @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<HTMLElement | null>>;
activeIndex: number | null;
onMatch?: (index: number) => void;
onTypingChange?: (typing: boolean) => void;
enabled?: boolean;
findMatch?: (
list: Array<string | null>,
typedString: string
) => string | null | undefined;
resetMs?: number;
ignoreKeys?: Array<string>;
selectedIndex?: number | null;
}Usage Example:
import { useTypeahead, useListNavigation } from '@floating-ui/react';
function SearchableMenu() {
const [activeIndex, setActiveIndex] = useState<number | null>(null);
const [typing, setTyping] = useState(false);
const listRef = useRef<Array<HTMLElement | null>>([]);
const labelRef = useRef<Array<string | null>>([]);
const { refs, context } = useFloating({
open: true,
onOpenChange: () => {},
});
const listNavigation = useListNavigation(context, {
listRef,
activeIndex,
onNavigate: setActiveIndex,
});
const typeahead = useTypeahead(context, {
listRef: labelRef,
activeIndex,
onMatch: setActiveIndex,
onTypingChange: setTyping,
});
const { getFloatingProps, getItemProps } = useInteractions([
listNavigation,
typeahead,
]);
const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];
return (
<div ref={refs.setFloating} {...getFloatingProps()}>
{typing && <div>Typing...</div>}
{items.map((item, index) => (
<div
key={item}
ref={(el) => {
listRef.current[index] = el;
labelRef.current[index] = item;
}}
tabIndex={activeIndex === index ? 0 : -1}
style={{
background: activeIndex === index ? 'lightblue' : 'white',
padding: '8px',
}}
{...getItemProps()}
>
{item}
</div>
))}
</div>
);
}Context provider for managing lists of floating items with element and label references.
/**
* Context provider for managing floating lists
* @param props - List context configuration
* @returns Context provider for floating lists
*/
interface FloatingListProps {
children: React.ReactNode;
elementsRef: React.MutableRefObject<Array<HTMLElement | null>>;
labelsRef?: React.MutableRefObject<Array<string | null>>;
}
declare const FloatingList: React.FC<FloatingListProps>;Registers an item within a FloatingList context and provides ref management.
/**
* Registers item in floating list context
* @param props - List item configuration
* @returns Ref and index for the list item
*/
function useListItem(props?: UseListItemProps): {
ref: React.RefCallback<HTMLElement>;
index: number;
};
interface UseListItemProps {
label?: string | null;
}Usage Example:
import { FloatingList, useListItem } from '@floating-ui/react';
function ListWithItems() {
const elementsRef = useRef<Array<HTMLElement | null>>([]);
const labelsRef = useRef<Array<string | null>>([]);
return (
<FloatingList elementsRef={elementsRef} labelsRef={labelsRef}>
<Item label="First item" />
<Item label="Second item" />
<Item label="Third item" />
</FloatingList>
);
}
function Item({ label }: { label: string }) {
const { ref, index } = useListItem({ label });
return (
<div ref={ref} data-index={index}>
{label}
</div>
);
}Creates a single tab stop with arrow key navigation for composite widgets per WAI-ARIA guidelines.
/**
* Single tab stop with arrow key navigation for composite widgets
* @param props - Composite widget configuration
* @returns Composite widget container
*/
interface CompositeProps {
children: React.ReactNode;
role?: string;
orientation?: 'horizontal' | 'vertical' | 'both';
loop?: boolean;
cols?: number;
disabledIndices?: Array<number>;
activeIndex?: number;
onNavigate?: (activeIndex: number) => void;
itemSizes?: Array<number>;
dense?: boolean;
render?: React.ComponentPropsWithoutRef<any>;
}
declare const Composite: React.FC<CompositeProps>;Individual item within a Composite widget with proper focus management.
/**
* Individual item within Composite widget
* @param props - Composite item configuration
* @returns Composite item element
*/
interface CompositeItemProps {
children: React.ReactNode;
role?: string;
render?: React.ComponentPropsWithoutRef<any>;
}
declare const CompositeItem: React.FC<CompositeItemProps>;Usage Example:
import { Composite, CompositeItem } from '@floating-ui/react';
import { useState } from 'react';
function Toolbar() {
const [activeIndex, setActiveIndex] = useState(0);
return (
<Composite
role="toolbar"
orientation="horizontal"
activeIndex={activeIndex}
onNavigate={setActiveIndex}
>
<CompositeItem role="button">
<button>Cut</button>
</CompositeItem>
<CompositeItem role="button">
<button>Copy</button>
</CompositeItem>
<CompositeItem role="button">
<button>Paste</button>
</CompositeItem>
</Composite>
);
}