Multi-Select Combobox
A chip-and-search combobox with full keyboard control and a selection cap.
- Category
- Components
- Added
- 2026-09-01
- Deps
- 1
- Updated
- 2026-09-01
This is a viberdy Pro component
The live preview, the props panel and the write-up are open to everyone. The full source, the AI prompt and CLI install are part of Pro.
Props
"use client";
import { useMemo, useState, type KeyboardEvent } from "react";
import { Check, ChevronDown, X } from "lucide-react";
const OPTIONS = [
"React", "Vue", "Svelte", "Next.js", "Nuxt", "Astro", "Remix", "SolidJS", "Qwik", "Angular",
];
export function MultiSelectCombobox({
maxSelected = 5,
placeholder = "Select frameworks...",
}: {
maxSelected?: number;
placeholder?: string;
}) {
const [selected, setSelected] = useState<string[]>(["React", "Next.js"]);
const [query, setQuery] = useState("");
// ---------------------------------------------------------------
// Full source available with a viberdy Pro subscription.
// https://viberdy.dev/pricing
// ---------------------------------------------------------------
}About this component
A native <select multiple> is nearly unusable without a Ctrl/Cmd-click, and most 'multi-select' components on the web are really just a styled dropdown that reopens after every click, forcing users to hunt for the trigger again and again. This one keeps a single input as the combined search box, trigger, and removal target, with selected values rendered as chips inline before the caret. The state that actually makes it work is a separate activeIndex tracked against the FILTERED results array rather than the full option list, so arrow-key navigation stays correct as the user types and the list shrinks — indexing into the wrong array here is the most common bug in hand-rolled comboboxes. Reach for this over a native multi-select whenever the option count is large enough to need search, or the design calls for visible chips; drop to a simple checkbox list once there are only three or four options, where a combobox adds more interaction cost than it saves. Caveat: this is a controlled, uncontrolled-focus implementation — for production use, swap in Radix's Combobox primitives for full ARIA compliance and focus trapping.
Curator’s note
Backspace-to-remove-last-chip only fires when the query is empty — otherwise deleting search text would also silently delete a selection, which is the classic multi-select input footgun.
Pairs well with
Matched on shared tags and category — the entries most likely to be used alongside this one.
Floating Label Input
componentsA text input whose label floats from placeholder position into a caption on focus.
File Upload Dropzone
componentsA real drag-and-drop file zone with a live dragover state and file chips.
Date Range Picker
componentsA click-twice range calendar with a live hover preview and quick presets.