# typeahead Jumps to the item whose text starts with what the user typed. Characters typed within `timeout` ms accumulate ("ap" finds Apple before Avocado), repeating one character cycles through the items that start with it, and matching ignores case and accents ("e" finds "Éclair"). [rovingFocus](roving-focus) and [activeDescendant](active-descendant) run it from their `typeahead` option; call it directly in a list that handles its own keys. ```ts Signatures function typeahead(timeout?: number): Typeahead; function isTypeaheadKey(e: KeyboardEvent): boolean; interface Typeahead { (key: string, items: HTMLElement[], current: HTMLElement | null): HTMLElement | null; active(): boolean; } ``` | Argument | Type | Default | What it does | |---|---|---|---| | `timeout` | `number` | `1000` | ms after the last character before the search starts over. | The returned search takes the key, the items and the current item, and returns the item to move to, or `null` when nothing moves, which includes the current item staying the best match. Text is matched on `data-text-value`, else the item's trimmed text. Disabled items are the caller's to filter out. `isTypeaheadKey(e)` is true for one printable character with no modifier. A Space continues a search in progress but never starts one, so Space keeps its own meaning (select, toggle) on a fresh press. `active()` is true while a search is running: check it after the call to know whether the key was taken, and prevent its default when it was. ## In a template of your own ```ehtml app/shared/templates/color-list/index.ehtml import { typeahead, isTypeaheadKey, type Typeahead } from "@elements/ui/behaviors"; function onKeyDown(e: KeyboardEvent, search: Typeahead) { if (!isTypeaheadKey(e)) { return; } let list = e.currentTarget as HTMLElement; let items = Array.from(list.querySelectorAll("[role=option]")); let match = search(e.key, items, document.activeElement as HTMLElement | null); if (match) { match.focus(); } if (match || search.active()) { e.preventDefault(); } } ``` ## Writes Nothing. ## Used by [DropdownMenu](../templates/dropdown-menu), [ContextMenu](../templates/context-menu), [Menubar](../templates/menubar), [Select](../templates/select), [Tree](../templates/tree), and every template with a `typeahead` option on roving focus or active descendant.