FormInputField

A labelled native input with reactive values, optional icons and built-in numeric step controls.

FormInputField

View source · API reference

Edit workspace details

Type an email, adjust the seat count and lock the fields. The summary reads the same refs as the inputs.

<RegorApp id="form-input-field-demo" src="./playground.ts"/>
import {
  defineButtonComponents,
  defineFlexComponents,
  defineFormComponents,
  defineFormInputField,
  defineGridComponents,
  defineIconComponents,
  definePanelComponents,
} from '@purestack/ts-components'
import { lucide_mail } from '@purestack/ts-svg-icons'
import {
  type ComputedRef,
  computed,
  createApp,
  defineComponent,
  html,
  type Ref,
  ref,
} from 'regor'

export interface FormInputFieldExample {
  contactEmail: Ref<string>
  seats: Ref<number | string>
  locked: Ref<boolean>
  summary: ComputedRef<string>
}

const formInputFieldExampleTemplate = html`<Flex direction="column">
  <Grid columns="1" columnsSm="2">
    <FormInputField
      id="input-email"
      label="Contact email"
      name="email"
      type="email"
      autocomplete="email"
      icon="lucide:mail"
      placeholder="you@example.com"
      :model="contactEmail"
      :disabled="locked"
    />
    <FormInputField
      id="input-seats"
      label="Seats"
      type="number"
      min="1"
      step="1"
      :model="seats"
      :disabled="locked"
    />
  </Grid>
  <FormCheck id="input-lock" label="Lock fields" :checked="locked" />
  <FormStatus>{{ summary }}</FormStatus>
</Flex>`

function createFormInputFieldExample(): FormInputFieldExample {
  const contactEmail = ref('')
  const seats = ref<number | string>(3)
  const locked = ref(false)
  return {
    contactEmail,
    seats,
    locked,
    summary: computed(
      () => `${seats()} seats · ${contactEmail() || 'No email entered'}`,
    ),
  }
}

const component = defineComponent<FormInputFieldExample>(
  formInputFieldExampleTemplate,
  {
    context: createFormInputFieldExample,
  },
)
const icons: Record<string, string> = { 'lucide:mail': lucide_mail }

createApp(
  {
    components: {
      FormInputFieldExample: component,

      ...defineFlexComponents(),
      ...definePanelComponents(),
      ...defineButtonComponents(),
      ...defineFormComponents(),
      ...defineFormInputField(),
      ...defineGridComponents(),
      ...defineIconComponents((name) => icons[name] ?? ''),
    },
  },
  {
    selector: 'app#form-input-field-demo',
    template: html`<FormInputFieldExample />`,
  },
)

Native input types

Use browser-native controls for dates, passwords and other structured input.

<Grid columns="1" columnsSm="2">
  <FormInputField id="input-date" label="Review date" type="date" />
  <FormInputField
    id="input-password"
    label="New password"
    type="password"
    autocomplete="new-password"
    placeholder="Enter a password"
  />
</Grid>

Behavior and accessibility

Visible labels are associated with generated or explicit IDs. Extra native attributes and events are inherited by the input. Number step buttons clamp to min; max and other native constraints still need form validation. Bind a ref rather than an evaluated ref value.

API reference

FormInputField 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<string | number>
Default
ref('')

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

type

RefOrValue<FormInputFieldType>
Default
text

Native input type: text, email, password, number, tel, url, search, date, time, datetime-local, month, week or color.

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.

min

RefOrValue<number | string>
Default
not set

Minimum numeric value. The number step buttons clamp to this value; native validation also uses it.

step

RefOrValue<number | string>
Default
1 for step buttons

Positive numeric increment. Invalid or non-positive values fall back to 1 for the step buttons.

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
not set

Trailing registered SVG icon. Keep the field label visible; an icon is not a replacement for its accessible name.

Composition

No slots. Input events remain native; model is the two-way value contract. Register defineFormInputField and defineIconComponents when using icons.