Skip to content

Components

Searchable Select Menus — the 20-Option Rule and the Keyboard Contract

Native Below 20 Options, Searchable Above — and Why "No Matches" Needs an Action
Written by Aiden Wood Founder and Lead Design Engineer
📜 🔍 ✅

The native <select> is criminally underrated — free keyboard support, free mobile UI, free form integration. It has exactly one scaling problem: past a couple dozen options it becomes a scavenger hunt, and your country picker, assignee dropdown or category selector has 200 entries.

The rule of thumb: under ~20 options, stay native. Over, go searchable. Velocity X's standard-searchable-select-menu is the upgrade path — same job as a select, plus a filter input, minus a dependency.

The Money Pattern

It's a controlled popover with a filter and a highlighted index — the state is three values, not a state machine:

const [open, setOpen] = useState(false);
const [query, setQuery] = useState('');
const [hi, setHi] = useState(0); // highlighted index

const visible = useMemo(() =>
  options.filter(o => o.label.toLowerCase().includes(query.toLowerCase())),
  [options, query]);

const onKeyDown = (e: KeyboardEvent) => {
  if (e.key === 'ArrowDown') setHi(h => Math.min(h + 1, visible.length - 1));
  if (e.key === 'ArrowUp')   setHi(h => Math.max(h - 1, 0));
  if (e.key === 'Enter')     { select(visible[hi]); setOpen(false); }
  if (e.key === 'Escape')    setOpen(false);
};

Reset hi to 0 whenever the query changes — the stale-highlight bug (arrow keys pointing at an option that's no longer visible) is the most common defect in hand-rolled versions. And focus stays in the filter input while arrows move the highlight: the combobox pattern, same as autocomplete.

The Catch

"No matches" is a dead end unless you give it an action. If users can create options (tags, clients, categories), the empty state becomes Create "velocity" — the single most-loved feature in this component class. If they can't, say what the list actually contains ("No team members match") so the user knows whether to fix the spelling or give up.

On mobile, think hard before replacing native: the OS picker is familiar, thumb-reachable and free. The searchable menu earns its place on desktop information density; a responsive variant that falls back to native under 640px is often the honest answer.

The Verdict

Native until it hurts, searchable after, combobox keyboard contract always, and an empty state with a verb in it. The finished menu lives in Velocity X's Standard Overlays & Menus — source you own, next to the command palette that shares its keyboard DNA.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.