Inspector Combobox

Settings row for a list too long to read: pressing it opens a width-matched list with a search field, the keyboard walking the results while focus stays in the field. Options carry groups, descriptions, swatches and search keywords, and `multiple` turns the row into a counted multi-select.

Installation

Adds the component and everything it depends on to your project.

npx shadcn add https://ui.beste.co/component/r-base/inspector-combobox

New here? Read the installation guide.

Usage

The import and the props worth knowing about, in one place.

import { InspectorCombobox } from "@/components/beste/component/inspector-combobox";

const pages = [
  { value: "home", label: "Home", group: "Pages" },
  { value: "pricing", label: "Pricing", group: "Pages" },
  { value: "docs", label: "Documentation", group: "Pages", keywords: ["help", "guide"] },
  { value: "cart", label: "Cart", group: "Shop" },
];

<InspectorCombobox label="Link to" options={pages} defaultValue="pricing" />

// Controlled. The argument is a string here and an array under `multiple`, so
// narrow it at the call site, which is what knows which it asked for.
<InspectorCombobox
  label="Link to"
  options={pages}
  value={page}
  onValueChange={(next) => setPage(next as string)}
  onOpenChange={(open) => console.log("list open:", open)}
  searchable                       // on by default past eight options
  searchPlaceholder="Find a page"
  placeholder="Choose a page"      // shown while nothing is selected
  emptyMessage="No page matches"
  clearable                        // adds a "Clear Link to" button at the foot
  tone="outline"                   // "muted" (default) | "outline" | "ghost"
  size="sm"                        // "sm" | "default" | "lg"
/>

// Several at once: the row counts them, and the list stays open between presses
<InspectorCombobox
  label="Categories"
  multiple
  max={3}
  options={["Editorial", "Commerce", "Marketing", "Docs"]}
  value={categories}
  onValueChange={(next) => setCategories(next as string[])}
/>

// Options can carry a mark and a second line
<InspectorCombobox
  label="Theme"
  options={[
    { value: "sand", label: "Sand", swatch: "#d6cbb8", description: "Warm neutral" },
    { value: "slate", label: "Slate", swatch: "#64748b", description: "Cool neutral" },
  ]}
/>

Playground

Turn the props on the right; the snippet under them is what you would write to get what you see.

Usage
import { InspectorCombobox } from "@/components/beste/component/inspector-combobox";

<InspectorCombobox
  label="Link to"
  className="w-72"
  defaultValue="pricing"
  options={[{"value":"home","label":"Home","group":"Pages"},{"value":"pricing","label":"Pricing","group":"Pages"},{"value":"about","label":"About","group":"Pages"},{"value":"contact","label":"Contact","group":"Pages"},{"value":"blog","label":"Blog index","group":"Pages"},{"value":"changelog","label":"Changelog","group":"Pages"},{"value":"docs","label":"Documentation","group":"Pages","keywords":["help","guide"]},{"value":"cart","label":"Cart","group":"Shop"},{"value":"checkout","label":"Checkout","group":"Shop"},{"value":"account","label":"Account","group":"Shop"}]}
/>

Keyboard and gestures

Every one of these is in the component already. They are listed because a props table cannot mention a gesture, so nothing else on this page can tell you they exist.

Down / UpMove through the results without leaving the search field
Home / EndJump to the first or last result
EnterChoose the active result
EscapeClose the list, leaving the value alone
TypingFilters on the label, the value, the description and any keywords

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
label*stringLabel rendered on the left, inside the row.
iconLucideIconOptional leading icon shown before the label.
options(string | InspectorComboboxOption)[]The options on offer.
valuestring | string[]Controlled selection: a string, or an array of them with `multiple`. Pair it with `onValueChange`.
defaultValuestring | string[]Initial selection in uncontrolled mode.
onValueChange(value: ComboboxValue) => voidFires on every selection. The argument is a string, or an array of them when `multiple` is set — narrow it at the call site, which knows which it asked for.
onOpenChange(open: boolean) => voidFires when the list opens or closes.
multiplebooleanChoose several. The row then counts them and the list keeps itself open.
maxnumberCeiling on how many may be chosen at once, with `multiple`.
searchablebooleanShow the search field. Defaults to on once there are more than eight options, which is the point at which reading the list stops being faster than typing.
searchPlaceholderstringGhost text for the search field.
placeholderstringShown in the row while nothing is selected.
emptyMessagestringMessage shown when nothing matches the search.
clearablebooleanOffer a clear button at the foot of the list once something is selected.
disabledbooleanBlock interaction and dim the row.
tone"muted" | "outline" | "ghost""muted"Surface treatment: filled (default), hairline outline, or bare until hover.
size"sm" | "default" | "lg""default"Row height preset.
classNamestring
aria-labelstringAccessible name. Falls back to `label`.

More Inspector components

View all Inspector
Dark Mode

Inspector Segmented

Settings row whose choices sit side by side on the right, with a marker that slides between them: the readable alternative to a switch when the two states deserve names, and the compact one to a select at three or four options.

Inspector Corners

Settings row for the four corners of a box: the row carries a border-radius shorthand summary and a glyph rounded to match, and opens a square where each field sits on the corner it rounds.

Inspector Spacing

Settings row for the four edges of a box: the row carries a CSS-shorthand summary, and opens a cross where each field sits on the edge it sets, tied together or not.

px

Inspector Dimensions

Width and height on one row, with the lock between them: while it is closed, editing one scales the other by the ratio the pair had when the lock closed. Both fields are as wide as the largest number they can hold, so typing never shifts the row.

landing pagesaaspricing

Inspector Tags

Settings block for a list of short strings: tags are typed one after another and wrap under the label, a comma or a paste splits several at once, and Backspace on an empty field reaches back into the list. Collapsible, so a long list folds down to the height of a row with the count still on it.

Inspector Range

Settings row for a span rather than a value: two thumbs on the row itself, the band between them filling it, and both ends of the pair read out on the right. Ticks, tones and thumb states follow inspector-slider exactly, appearing on hover.