gridland
Components

SelectInput

A single-selection list with radio indicators and groups

A single-selection list with radio indicators, keyboard navigation, group headers, and a submitted state.

SelectInput
?

Run demo

Terminal
bunx @gridland/demo select-input
Terminal
curl -fsSL https://raw.githubusercontent.com/thoughtfulllc/gridland/main/scripts/run-demo.sh | bash -s select-input

Installation

bunx shadcn@latest add @gridland/select-input

Usage

import { SelectInput } from "@/components/ui/select-input"
import { useKeyboard } from "@gridland/utils"
<SelectInput
  items={[
    { label: "TypeScript", value: "ts" },
    { label: "JavaScript", value: "js" },
    { label: "Python", value: "py" },
  ]}
  title="Select a language"
  useKeyboard={useKeyboard}
  onSubmit={(value) => console.log("Selected:", value)}
/>

Examples

Controlled

Use value and onChange to control the selection externally.

Controlled
const [value, setValue] = useState<string>("ts")

<SelectInput
  items={[
    { label: "TypeScript", value: "ts" },
    { label: "JavaScript", value: "js" },
    { label: "Python", value: "py" },
  ]}
  value={value}
  onChange={setValue}
  title="Select a language"
  useKeyboard={useKeyboard}
  onSubmit={(value) => console.log("Selected:", value)}
/>

Default Value

Set the initially selected item in uncontrolled mode.

Default value
<SelectInput
  items={[
    { label: "TypeScript", value: "ts" },
    { label: "JavaScript", value: "js" },
    { label: "Python", value: "py" },
  ]}
  defaultValue="ts"
  title="Select a language"
  useKeyboard={useKeyboard}
  onSubmit={(value) => console.log("Selected:", value)}
/>

Groups

Use the group field on items to render group headers with separators.

With groups
<SelectInput
  items={[
    { label: "TypeScript", value: "ts", group: "Languages" },
    { label: "Python", value: "py", group: "Languages" },
    { label: "React", value: "react", group: "Frameworks" },
    { label: "Vue", value: "vue", group: "Frameworks" },
  ]}
  title="Select a tool"
  useKeyboard={useKeyboard}
  onSubmit={(value) => console.log(value)}
/>

Disabled Items

Disable individual items so they cannot be selected.

Disabled items
<SelectInput
  items={[
    { label: "TypeScript", value: "ts" },
    { label: "JavaScript", value: "js", disabled: true },
    { label: "Python", value: "py" },
  ]}
  title="Select a language"
  useKeyboard={useKeyboard}
  onSubmit={(value) => console.log(value)}
/>

Required

Show a required indicator and use invalid to display an error state.

Required with validation
<SelectInput
  items={[
    { label: "TypeScript", value: "ts" },
    { label: "JavaScript", value: "js" },
    { label: "Python", value: "py" },
  ]}
  required
  invalid={!hasSelected}
  title="Select a language"
  useKeyboard={useKeyboard}
  onSubmit={(value) => console.log(value)}
/>

Disabled

Disable the entire component. Navigation and submission are blocked.

Disabled
<SelectInput
  items={[
    { label: "TypeScript", value: "ts" },
    { label: "JavaScript", value: "js" },
  ]}
  disabled
  title="Select a language"
  useKeyboard={useKeyboard}
/>

Placeholder

Show placeholder text when the items list is empty.

Placeholder
<SelectInput
  items={[]}
  placeholder="No options available"
  title="Select a language"
  useKeyboard={useKeyboard}
/>

Controls

  • ↑/↓ or j/k: Navigate and select
  • Enter: Submit selected item

API Reference

SelectInput

PropTypeDefaultDescription
itemsSelectInputItem<V>[][]Array of selectable items
defaultValueV-Initially selected value (uncontrolled)
valueV-Selected value (controlled)
onChange(value: V) => void-Called when selection changes
disabledbooleanfalseDisable the entire component
invalidbooleanfalseShow error state with destructive styling
requiredbooleanfalseShow required indicator (*) next to title
placeholderstring-Placeholder text when items list is empty
titlestring"Select"Title shown next to the diamond indicator
submittedStatusstring"submitted"Status text shown after submit
limitnumber12Max visible rows before scrolling
highlightColorstringtheme.primaryColor of the highlighted item
onSubmit(value: V) => void-Called on Enter with the selected value
useKeyboard(handler: (event: any) => void) => void-Keyboard hook from @opentui/react

SelectInputItem

FieldTypeDescription
labelstringDisplay text
valueVItem value
keystring?Optional React key
groupstring?Group header label
disabledboolean?Disable individual item