COMBOBOX
combobox.tsx
Accessible combobox with value source management, keyboard nav, async search.
StarkWHAT THIS PATTERN TEACHES
How to build a combobox that correctly manages two value sources (display value when closed, search query when open) without losing keystrokes when the dropdown closes mid-type.
WHEN TO USE THIS
Any searchable dropdown, autocomplete, or type-ahead selector. Especially important when the dropdown can close during typing (short queries, no results).
AT A GLANCE
function useCombobox<T>(options: ComboboxOptions<T>) {
const [isOpen, setIsOpen] = useState(false)
const [query, setQuery] = useState("")
// Two value sources: display vs search
}FRAMEWORK IMPLEMENTATIONS
TypeScript
import { useState, useRef, useCallback, useEffect } from 'react';
// Two value sources: display (closed) vs search (open)
// Never let close events switch the source mid-keystroke
interface ComboboxOptions<T> {
items: T[];
getLabel: (item: T) => string;
onSelect: (item: T) => void;
filterFn?: (item: T, query: string) => boolean;
}
function useCombobox<T>({ items, getLabel, onSelect, filterFn }: ComboboxOptions<T>) {
const [isOpen, setIsOpen] = useState(false);
const [query, setQuery] = useState("");
const [selectedIndex, setSelectedIndex] = useState(-1);
const [selectedItem, setSelectedItem] = useState<T | null>(null);
const inputRef = useRef<HTMLInputElement>(null);
// Display value when closed, search query when open
const displayValue = isOpen