MeDo

Two Thousand Users, One Typing Box.

A combobox is what a select becomes when the list outgrows scrolling — type to filter, arrow keys to move, Enter to commit. Describe your data and MeDo generates the filtering, the keyboard model, async loading, and the free-text edge cases in one React + Tailwind component.

Combobox
Combobox

Scrolling Is Not a Search Strategy

The moment your option list passes about twenty items, a plain select stops being a form control and becomes a scavenger hunt — nobody scrolls 2,000 users to find Priya Nair, they give up and type "pri" into Slack instead. A combobox meets that instinct: the list stays for browsing and recognition, but typing does the actual finding, which is why every assignee picker, country selector and tag input at scale converged on this pattern. The trap is that a combobox is not a select with a search box bolted on. Filtering changes the keyboard contract (arrows move a highlight, Enter commits, Escape must restore the prior value), it changes the accessibility contract (aria-activedescendant or focus management, announced result counts), and it changes failure modes (empty states, async races where stale results overwrite fresh ones). Generating it from a prompt that spells out those contracts beats assembling them from four libraries that each solve one.

4 plantillas

Plantillas de Combobox que puedes generar

Cada plantilla es un prompt real, no una captura de pantalla. Cópialo en cualquier editor de IA o ejecútalo en MeDo y obtén código React + Tailwind.

PopularAssignee Picker

Team Member Combobox With Avatars

The classic large-dataset case: pick one person from thousands, filtered by name, with recent collaborators pinned above the results.

Create a single-select combobox for assigning a task to one of 2,000 workspace members, each with name, avatar URL and role. The collapsed trigger is a 40px input-like button showing the selected member as avatar-plus-name, or the placeholder "Assign to…" in zinc-400. On open, render a 320px-max-height popover listbox: a "Suggested" group pinned at top with the five most recently assigned members that survives filtering, then filtered results below. Match case-insensitively on name with a 150ms debounce, highlight the matching substring in indigo-600, and show a "Showing 50 of N" footer when results exceed 50. Arrow keys move the highlight with aria-activedescendant, Enter commits, Escape closes and restores the prior selection. Include a clearable X button and an empty state quoting the query with no results.

Prueba en MeDo
API-backedAsync Search

Server-Filtered Combobox With Race Protection

For datasets that live behind an API or a search index. Debounce, abort stale requests, and show loading honestly — the parts that break silently in production.

Create an async combobox that searches a companies API endpoint on every query. Debounce input at 250ms, abort the in-flight request with an AbortController when a new one starts, and ignore responses that arrive out of order so a slow result for an old query never overwrites a fresh one. While loading, keep the previous results visible and show a subtle spinner in the input's right edge rather than blanking the list. Render each result with company name, domain, and employee count. Handle failure with an inline "Search failed — retry" row that re-triggers the last query on click. Require at least two characters before searching, and show a hint row "Keep typing to search companies" below it. Collapsed state shows the chosen company as a removable chip with its domain in grey.

Prueba en MeDo
Multi-selectCreatable Tags

Tag Input That Creates Missing Options

A multi-select combobox where the taxonomy is a suggestion, not a cage: type something new and it becomes a tag, with deduplication built in.

Create a multi-select creatable combobox for tagging articles. Selected values render as removable chips inside a wrapping input container; Backspace with an empty query removes the last chip. The dropdown filters a preset tag taxonomy case-insensitively, hides options that are already selected, and always appends a final row "Create tag "<query>"" when the query is non-empty and not an exact case-insensitive match of an existing tag, disabled when the query is shorter than two characters. Enter or click commits the highlighted row; arrows move the highlight across both option rows and the create row. Cap selection at 8 tags and show a counter "5/8" at the container edge, disabling the input beyond the cap. Announce result counts through a visually hidden aria-live region.

Prueba en MeDo
Smart matchingMulti-Field Search

Combobox Matching Across Hidden Fields

Users type what they remember — a dial code, a domain, a nickname. Match on every field, display only the primary one, and the hit rate jumps.

Create a country combobox over 240 entries where each record has a primary display name, localized names, ISO code and dial code. The query matches any of these fields case-insensitively, so "49", "DEU" and "germany" all surface Germany, but only the display name and flag render in the list. Rank results: prefix matches on the display name first, then other-field matches. Highlight matched substrings wherever they occur and show the dial code in grey at the row's right edge. On mobile the dropdown becomes a bottom sheet occupying 60% of the viewport height. The collapsed trigger shows flag and name; keyboard support includes Home and End jumping to the first and last highlighted options.

Prueba en MeDo

Cómo personalizar tu Combobox

Set the threshold where typing beats scrolling

Below roughly fifteen options, a plain select is faster — no keyboard round trip, no popup. Ask for a combobox only when the list is genuinely large or the values are unfamiliar, and say the expected count in the prompt so matching, virtualization and the result-count footer are sized to reality.

Decide early whether free text is allowed

A combobox can be pick-one-from-list only, or it can offer "Add "acme-co" as new" when nothing matches. These are different products: the first is a filter, the second is a creation flow with validation and deduplication. Name the behavior explicitly — generated code will not infer it from your data.

Debounce async filtering and cancel stale requests

If options come from an API, every keystroke should debounce (150–250ms) and abort the previous request, or a slow response for "a" can land after the fast one for "an" and show the wrong list. State both behaviors in the prompt; they are invisible in a demo and maddening in production.

Pin frequent options above the filter

In an assignee picker, the current user and recent collaborators matter more than alphabetical order. Ask for a "Suggested" group that survives filtering, so the common case is one click even though the long tail still needs typing.

Quién usa el componente Combobox

Project management assignee field

A task detail view where the Assignee control filters 2,000 workspace members by name, shows avatars and a Suggested group pinned above the results, and commits on Enter so power users never touch the mouse.

E-commerce address form

A country selector over 240 entries with localized names and dial-code hints, where typing "44" or "united ki" both reach the United Kingdom — impossible in a scrolled select ordered by one field.

CRM company lookup

Attaching a deal to an existing account, with async search against the CRM, a "Create new account" row when nothing matches, and the selected company rendered as a removable chip in the collapsed state.

Admin panel multi-select tags

Labeling a support ticket with multiple tags from a shared taxonomy: type to filter, Enter adds a chip, Backspace removes the last one, and already-applied tags disappear from the dropdown results.

Patrones de Combobox para distintos sitios web

El mismo componente combobox, adaptado al tipo de sitio donde se publica.

01 / 04

SaaS Admin and Settings Pages

Every owner-picker, workspace-switcher-in-a-form and "route these alerts to" field is a combobox over a growing member list. Pin the current user and recent choices so the 90% case never needs typing at all.

Estilos y variantes de Combobox

Elige la variante que encaje con el resto de la página y genérala.

01 / 04

Input-Style Trigger

The trigger looks exactly like a text input — same border, height and focus ring as neighboring fields — because semantically it is one. The right default inside any form, where a button-styled control reads as an action rather than a field.

Combobox en React, Next.js, Vue y Svelte

React, Next.js, Vue 3, SvelteKit, Astro o HTML puro: el mismo combobox, seis formas de integrarlo.

01 / 03

React Combobox

The core loop in miniature: filter on a memoized query, track a highlight index for the arrow keys, and let aria-activedescendant keep the screen reader in sync with the visual highlight.

src/components/Combobox.tsx

const [query, setQuery] = useState('')
const [active, setActive] = useState(0)

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

<input
  role="combobox"
  aria-expanded={open}
  aria-controls="opts"
  aria-activedescendant={`opt-${active}`}
  value={query}
  onChange={(e) => { setQuery(e.target.value); setActive(0) }}
  onKeyDown={(e) => {
    if (e.key === 'ArrowDown') setActive((i) => Math.min(i + 1, results.length - 1))
    if (e.key === 'Enter') select(results[active])
  }}
/>

Cómo añadir tu Combobox a un proyecto

Cuatro pasos, desde elegir una plantilla de combobox hasta llevarlo a producción.

01~1min

Decide Select, Combobox, or Palette

Count your options and name your data. Under ~15 familiar options stay with a select; a large or unfamiliar dataset needs a combobox; app-wide action search is a command palette, which is a different component entirely.

02~2min

Describe Data and Matching Rules

In the MeDo prompt, state the field to match on, whether hidden fields (codes, aliases) participate, the debounce for async sources, and whether free text may create new values. These choices change the generated logic, not just the markup.

03~3min

Generate and Exercise the Keyboard

You get React + Tailwind with a live preview. Before styling anything, put your hands on the keyboard: arrows through every result, Enter to commit, Escape restoring the previous value, Tab closing cleanly. Fix behavior with follow-up prompts, not by editing handlers.

04~4min

Test the Edge States and Ship

Force the cases a demo hides: an empty result set, an API failure with retry, an out-of-order async response, and the selected value still visible after aggressive filtering. Then wire the field into your form.

Preguntas frecuentes sobre Combobox

When should I use a combobox instead of a select?

Use a select when the list is short (roughly under fifteen options) and the values are familiar — fixed plan tiers, a handful of statuses. Switch to a combobox when the list is long enough that scrolling stops scaling, or when users know roughly what they want and can type a fragment of it. A good test: if you would scroll the dropdown yourself to find an option, your users will resent doing it too.

Is a combobox the same as a command palette?

No, and confusing them produces the wrong component. A command palette (Cmd+K) searches actions and destinations across the whole app, usually opens from a global shortcut, and accepts fuzzy queries like "deploy prod". A combobox fills one form field with one value from a known dataset, opens from its own input, and matches on the value itself. If the user is filling in a field inside a form, it is a combobox; if they are telling the app where to go, it is a palette.

How do I make a combobox accessible?

The input carries role="combobox" with aria-expanded, aria-controls pointing at the listbox, and aria-activedescendant tracking the highlighted option as you press the arrow keys. The list container is role="listbox" with role="option" children, and a visually hidden live region announces things like "12 results available". MeDo generates this wiring from the prompt — it is the part of a combobox that is essentially impossible to retrofit correctly by hand-editing markup.

Can users type a value that is not in the list?

Only if you design for it. Prompt for a creatable combobox: when the filtered list is empty, render an "Add "<query>" as new" row that commits the raw text as the value, plus validation rules such as minimum length and duplicate checks. If values must come from the dataset, say "list-only, no free text" so the generated code shows a clear empty state instead of silently accepting arbitrary input.

How do I handle very large option lists without lag?

Two layers: debounce client-side filtering so it does not run on every keystroke, and window the rendered list so only the visible slice of options mounts — filtering 2,000 items is cheap, but rendering 2,000 DOM rows is not. If the dataset is bigger than a few thousand records or lives behind search infrastructure, move matching to an async endpoint and render a loading state between keystrokes.

Should the selected value stay visible while filtering?

In single-select comboboxes, yes — a common regression is the selected option vanishing from results once the query no longer matches it, which makes the field look empty even though a value is set. Ask for the selection to render as a persistent element in the trigger or as a "Current: X" row pinned above results, so the committed value survives any amount of typing.