Siteplane UI

Choosing selection controls

Choose between a fixed choice, a searchable choice, and free text.

Markdown

Match the value type

NeedComponentApplication value
One visible choiceRadioGroupSelected value
Several visible choicesCheckboxGroupArray of selected values
Short collapsed listSelectSelected value, or an array with multiple
Searchable list of known optionsComboboxSelected value(s), separate from the query
Free text with suggestionsAutocompleteInput text
Options presented as cardsRadioGroup or CheckboxGroup card styleSelected value, or an array of selected values
Always-visible single-choice listListBoxSelected value
One immediate preferenceSwitchBoolean checked state

Searchable choice

"use client";

import { UserIcon } from "lucide-react";
import {
  Combobox,
  ComboboxEmpty,
  ComboboxInput,
  ComboboxItem,
  ComboboxList,
  ComboboxPopup,
} from "@/siteplane/components/combobox";
import { Field, FieldLabel } from "@/siteplane/components/field";

const people = [
  "Mara Ellis",
  "Ben Carter",
  "Sofia Nguyen",
  "Priya Shah",
  "Nora Lind",
  "Sam Ortiz",
];

export default function Example() {
  return (
    <Field className="w-full max-w-sm">
      <FieldLabel>Assignee</FieldLabel>
      <Combobox items={people}>
        <ComboboxInput
          className="w-full"
          placeholder="Select a person"
          startAddon={<UserIcon />}
        />
        <ComboboxPopup>
          <ComboboxEmpty>No people found.</ComboboxEmpty>
          <ComboboxList>
            {(person: string) => (
              <ComboboxItem key={person} value={person}>
                {person}
              </ComboboxItem>
            )}
          </ComboboxList>
        </ComboboxPopup>
      </Combobox>
    </Field>
  );
}

A Combobox’s query is not the selected value. For object items, provide the string conversion and equality behavior described in its API. When filtering remotely, keep loading, empty, error, and selected-item display coherent; the component does not fetch data.

Free text

"use client";

import { SearchIcon } from "lucide-react";
import {
  Autocomplete,
  AutocompleteEmpty,
  AutocompleteInput,
  AutocompleteItem,
  AutocompleteList,
  AutocompletePopup,
} from "@/siteplane/components/autocomplete";

const projects = [
  "Website redesign",
  "Mobile app launch",
  "Billing migration",
  "Design system",
  "Customer onboarding",
  "Quarterly planning",
];

export default function Example() {
  return (
    <div className="w-full max-w-sm">
      <Autocomplete items={projects}>
        <AutocompleteInput
          aria-label="Search projects"
          placeholder="Search projects…"
          startAddon={<SearchIcon />}
        />
        <AutocompletePopup>
          <AutocompleteEmpty>No matching projects.</AutocompleteEmpty>
          <AutocompleteList>
            {(project: string) => (
              <AutocompleteItem key={project} value={project}>
                {project}
              </AutocompleteItem>
            )}
          </AutocompleteList>
        </AutocompletePopup>
      </Autocomplete>
    </div>
  );
}

Autocomplete can retain text that does not identify an option. Do not submit that text as a foreign key without validation. If the user must choose a known entity, use Combobox or Select.

Labels, disabled values, and reset

Give the trigger or input an accessible name. A placeholder is an entry hint, not a persistent label. Explain unavailable options when their reason matters. Keep stable values or keys, particularly while filtering or refreshing a collection.

Check each component’s native form support before relying on FormData. Controlled selection must be reset in application state. With multiple selection, CheckboxGroup, Select and Combobox use arrays of values, while Table reports a Set of keys or "all".

Integration

The Team settings example uses Select for visibility and Switch for independent notification preferences. Its full file includes the state and installation dependencies needed outside the docs.