FormSelectField

A labelled native select with typed option data, reactive selection and familiar keyboard behavior.

FormSelectField

View source · API reference

Choose a region

Select a region and inspect its stored value. The unavailable option stays visible but cannot be selected.

<RegorApp id="form-select-field-demo" src="./playground.ts"/>
import {
  defineFlexComponents,
  defineFormComponents,
  defineFormSelectField,
  defineIconComponents,
  type FormSelectOption,
  type FormSelectValue,
} from '@purestack/ts-components'
import { lucide_chevron_down } from '@purestack/ts-svg-icons'
import { createApp, defineComponent, html, type Ref, ref } from 'regor'

export interface FormSelectFieldExample {
  regionValue: Ref<FormSelectValue>
  regionOptions: FormSelectOption[]
  locked: Ref<boolean>
}

const formSelectFieldExampleTemplate = html`<Flex direction="column">
  <FormSelectField
    id="select-region"
    label="Deployment region"
    name="region"
    placeholder="Choose a region"
    :model="regionValue"
    :options="regionOptions"
    :disabled="locked"
  />
  <FormCheck id="select-lock" label="Lock selection" :checked="locked" />
  <FormStatus>Selected region: {{ regionValue || 'None' }}</FormStatus>
</Flex>`

function createFormSelectFieldExample(): FormSelectFieldExample {
  return {
    regionValue: ref<FormSelectValue>(''),
    locked: ref(false),
    regionOptions: [
      { label: 'Europe Central', value: 'eu-central' },
      { label: 'US East', value: 'us-east' },
      { label: 'Asia Pacific · unavailable', value: 'apac', disabled: true },
    ],
  }
}

const component = defineComponent<FormSelectFieldExample>(
  formSelectFieldExampleTemplate,
  {
    context: createFormSelectFieldExample,
  },
)
const icons: Record<string, string> = {
  'lucide:chevron-down': lucide_chevron_down,
}

createApp(
  {
    components: {
      FormSelectFieldExample: component,

      ...defineFlexComponents(),
      ...defineFormSelectField(),
      ...defineFormComponents(),
      ...defineIconComponents((name) => icons[name] ?? ''),
    },
  },
  {
    selector: 'app#form-select-field-demo',
    template: html`<FormSelectFieldExample />`,
  },
)

Required and disabled states

A placeholder is a disabled empty option. Validation belongs to the owning form.

<Grid columns="1" columnsSm="2">
  <FormSelectField
    id="select-required"
    label="Required choice"
    :required="true"
    placeholder="Select one"
    :options="[{ label: 'Stable', value: 'stable' }, { label: 'Preview', value: 'preview' }]"
  />
  <FormSelectField
    id="select-disabled"
    label="Unavailable selection"
    :disabled="true"
    :options="[{ label: 'Managed by policy', value: 'policy' }]"
  />
</Grid>

Behavior and accessibility

The browser owns the popup and its keyboard interactions. Native attributes and events are inherited by select. Numeric option values may be serialized as strings by native form submission; normalize values at your application boundary.

API reference

FormSelectField contract

Props below are the public template API. RefOrValue accepts a literal or a reactive ref; bind refs with a colon-prefixed attribute. Native attributes and events can be passed through the component root.

id

string
Default
generated

Unique control ID. Supply an explicit value when help text or another element needs to reference this control.

label

RefOrValue<string>
Default
not set

Visible label. Use language that describes the control or value in its surrounding context.

tone

RefOrValue<SemanticTone>
Default
inherited

Semantic intent: neutral, accent, secondary, info, success, warning, danger, feature, custom or ghost. The active skin supplies the colors.

variant

RefOrValue<ComponentVariant>
Default
surfaceAlt

Visual treatment. Accepts solid, surface, surfaceAlt, spotlight, glass, flat, flatAlt, flatSolid, outlineFill, outline, subtle, subtleBtn, link, sheen, underline, rail, bracket or none.

model

Ref<FormSelectValue>
Default
ref('')

Two-way value ref. Pass the ref itself with :model="fieldValue" so edits update application state.

name

RefOrValue<string>
Default
not set

Native form field name used during FormData serialization.

required

RefOrValue<boolean>
Default
false

Native required constraint. Validate the owning form before accepting its data.

autocomplete

RefOrValue<string>
Default
off

Native browser autofill hint, such as name, email or current-password.

placeholder

RefOrValue<string>
Default
not set

A short input hint shown while empty. Keep a separate visible label.

disabled

RefOrValue<boolean>
Default
false

Disables interaction. Use a bound boolean, for example :disabled="isLocked".

icon

RefOrValue<string>
Default
not set

Registered SVG icon name. In browser apps, include the icon in the resolver passed to defineIconComponents.

iconEnd

RefOrValue<string>
Default
lucide:chevron-down

Trailing registered icon. Include the default chevron in browser app icon registration.

options

RefOrValue<FormSelectOption[]>
Default
[]

Suggestion or select data. Each option has a label, an optional value and an optional disabled flag. Omitted values use the label.

Composition

No slots. Register defineFormSelectField and defineIconComponents. Pass FormSelectOption[] with options and a Ref<FormSelectValue> with model.

Option data

interface FormSelectOption {
  label: RefOrValue<string>
  value?: RefOrValue<string | number>
  disabled?: RefOrValue<boolean>
}

When value is omitted, the resolved label becomes the value.