Inspector Select

About this component

Inspector Select

Settings row that pairs a label with its current choice inside one pill, opening a width-matched dropdown below: option icons, colour swatches, descriptions and grouped sections, on top of the accessible shadcn select.

Usage

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

import { InspectorSelect } from "@/components/beste/component/inspector-select";

// Plain strings are enough for a simple list
<InspectorSelect label="Easing" options={["linear", "ease-in", "ease-out"]} defaultValue="ease-out" />

// Controlled, with a commit-shaped handler
<InspectorSelect
  label="Blend mode"
  value={blendMode}
  onValueChange={setBlendMode}
  onOpenChange={(open) => console.log("menu open:", open)}
  options={[
    { value: "normal", label: "Normal" },
    // Consecutive options sharing a group become one section, so the order
    // you write is the order that renders.
    { value: "multiply", label: "Multiply", group: "Darken", description: "Keeps the darker pixels" },
    { value: "screen", label: "Screen", group: "Lighten" },
    { value: "hue", label: "Hue", group: "Component", disabled: true },
  ]}
/>

// Icons and colour swatches, per option
<InspectorSelect
  label="Palette"
  icon={Palette}                 // row icon, before the label
  defaultValue="sunset"
  options={[
    { value: "sunset", label: "Sunset", swatch: "#f97316" },
    { value: "ocean", label: "Ocean", swatch: "#0ea5e9" },
  ]}
/>

<InspectorSelect
  label="Font"
  tone="outline"                 // "muted" (default) | "outline" | "ghost"
  size="sm"                      // "sm" | "default" | "lg"
  menuWidth="auto"               // "trigger" (default) matches the row width
  placeholder="Inherit"          // shown until something is selected
  emptyMessage="No fonts found"
  options={fonts}
/>

// Takes part in a form through the underlying select
<InspectorSelect label="Region" name="region" options={["EU", "US", "APAC"]} disabled={isSaving} />

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.

Enter / SpaceOpen the menu.
Arrow keysMove through the options; the value follows as you go.
Type a letterJump to the next option starting with it.
EscapeClose and keep what was there before.

Props

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

PropTypeDefaultDescription
label*string—Label rendered on the left, inside the row.
iconLucideIcon—Optional leading icon shown before the label.
options(string | InspectorSelectOption)[]—Plain strings for simple lists, or objects for icons, swatches and groups.
valuestring—Controlled value. Pair it with `onValueChange`.
defaultValuestring—Initial value in uncontrolled mode.
onValueChange(value: string) => void—
onOpenChange(open: boolean) => void—Fires when the menu opens or closes.
placeholderstring"Select"Shown in place of the value until something is selected.
emptyMessagestring"No options"Menu text when there is nothing to choose from.
menuWidth"trigger" | "auto""trigger"Menu width: match the row, or size to the longest option.
disabledboolean—Block 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.
namestring—Name of the underlying form control, so the row can take part in a form.
idstring—Id of the trigger, for an external `<label htmlFor>`.
classNamestring—
aria-labelstring—Accessible name. Omit it and the row reads as "{label}, {value}", which is usually what you want — the visible label and the value are both announced.

More Inspector components

View all Inspector
Dark Mode