Skip to main content

COMBOBOX

combobox.tsx

Accessible combobox with value source management, keyboard nav, async search.

Stark avatarStark

WHAT 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
← All Patterns