Skip to content

useTypeahead

Provides a matching callback that can be used to focus an item as the user types, often used in tandem with useListNavigation().

import {
  useFloating,
  useInteractions,
  useTypeahead,
} from '@floating-ui/react-dom-interactions';
 
// ...
const {context} = useFloating();
const {getReferenceProps, getFloatingProps} = useInteractions([
  useTypeahead(context, {
    // props
  }),
]);

Props

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

listRef

default: empty list

A ref which contains an array of strings whose indices match the HTML elements of the list.

activeIndex

default: null

The currently active index. This specifies where the typeahead starts.

onMatch

default: no-op

Callback invoked with the matching index if found as the user types.

const [open, setOpen] = useState(false);
const [activeIndex, setActiveIndex] = useState(null);
const [selectedIndex, setSelectedIndex] = useState(null);
 
useTypeahead(context, {
  onMatch: open ? setActiveIndex : setSelectedIndex,
});

enabled

default: true

Conditionally enable/disable the hook.

useTypeahead(context, {
  enabled: false,
});

findMatch

default: lowercase finder

If you'd like to implement custom finding logic (for example fuzzy search), you can use this callback.

useTypeahead(context, {
  findMatch: (list, typedString) =>
    list.find(
      (itemString) =>
        itemString?.toLowerCase().indexOf(typedString) === 0
    ),
});

resetMs

default: 1000

Debounce timeout which will reset the transient string as the user types.

ignoreKeys

default: []

Ignore additional keys on top of the navigation-related ones.

[
  'Home',
  'End',
  'Escape',
  'Enter',
  'Tab',
  'ArrowUp',
  'ArrowDown',
  'ArrowLeft',
  'ArrowRight',
];

selectedIndex

default: null

The currently selected index, if any.

Data

typing

This hook sets context.dataRef.current.typing = boolean to determine if the user is currently typing. If a select option needs to be selected with Space, but the typeahead also allows spaces, this can be used to conditionally run the handler.