primitives
EditableSelect
A combobox whose OPTIONS are an editable dictionary — the field IS a search input: type to filter, pick a row, or press Enter to add a new option inline. For a pure picker use `<MultiSelect>` / `<Select>`.
Install
Pull this component (and its dependencies) straight into your app via the shadcn CLI:
npx shadcn@latest add https://design.oapps.io/r/editable-select.jsonOr import from the workspace package:
import { EditableSelect } from "@8maverik8/design";Examples
Editable dictionary (single)
Focus the field and the list drops open; type to filter in place. Pick a row, or — when nothing matches — press Enter (or click the create row) to add the typed value. Each option carries a minimal × delete on hover. The new option auto-selects when the callback returns its value.
const [options, setOptions] = useState([
{ value: "sec", label: "seconds" },
{ value: "count", label: "count" },
{ value: "ms", label: "ms" },
]);
const [value, setValue] = useState<string[]>(["sec"]);
<EditableSelect
placeholder="Search or add a unit…"
value={value}
onChange={setValue}
options={options}
createLabel={(q) => `Add "${q}"`}
onCreateOption={(label) => {
const v = label.toLowerCase().replace(/[^a-z0-9]+/g, "_");
setOptions((o) => [...o, { value: v, label }]);
return v; // auto-selects
}}
onDeleteOption={(v) => setOptions((o) => o.filter((x) => x.value !== v))}
/>Guidelines
- Use for small, in-place-manageable dictionaries (units, directions, tags, statuses) where a separate CRUD screen would be overkill.
- Modify `<MultiSelect>` to do this.MultiSelect is a pure picker; EditableSelect is a distinct product (it mutates the option set). Keeping them separate keeps each one's contract clear.
- Pass `onCreateOption` / `onDeleteOption` to enable creating (Enter / the create row, when the query matches nothing) and the inline × delete. Return the new option's value from `onCreateOption` to auto-select it.
- Set `multiple` for many-valued fields; leave it off (default single) for single-value dictionaries like a metric's unit.