StackForm
Components

TextField

Single-line text input field with label, error, hint, and character counter

TextField renders a labeled, accessible <input> connected to the active form adapter via context. Error and hint states surface automatically — no prop wiring needed.

Enter your legal name.

Props

PropTypeRequiredDefaultDescription
namestringyesField name. Used as the form state key and to derive element IDs.
labelstringLabel text rendered above the input.
hintstringHelper text shown below the input when no error is present.
placeholderstringPlaceholder text for the input.
type'text' | 'email' | 'password' | 'search' | 'tel' | 'url''text'HTML input type.
disabledbooleanfalseDisables the input. Inherits from StackFormProvider if not set.
loadingbooleanfalseReplaces the input with a skeleton shimmer.
requiredbooleanfalseMarks the field as required. Appends * to the label.
maxLengthnumberMaximum character count. Required when showCount is true.
showCountbooleanfalseShows a character counter. Requires maxLength.
prefixReactNodeContent rendered before the input (e.g. an icon).
suffixReactNodeContent rendered after the input (e.g. a currency symbol).
classNamesTextFieldClassNamesTailwind class overrides per slot. Stacks with provider and core classes.
slotsTextFieldSlotsComponent overrides per slot. First non-null wins: field → provider → default.
slotProps{ wrapper?, label?, input?, error?, hint?, prefix?, suffix?, counter? }Extra props passed to each slot. Field-level replaces provider-level per key.
onValueChange(value: string) => voidCalled after onChange with the new value.
validate(value: string) => string | undefined | Promise<string | undefined>Field-level validator. Runs on blur.

Slots

SlotProp interfaceDescription
WrapperWrapperSlotPropsOuter container element
LabelLabelSlotPropsLabel element
InputTextInputSlotPropsThe <input> element
ErrorErrorSlotPropsError message
HintHintSlotPropsHint/helper text
PrefixPrefixSlotPropsPrefix content wrapper
SuffixSuffixSlotPropsSuffix content wrapper
CounterCounterSlotPropsCharacter counter

classNames

KeyApplied to
wrapperOuter container
labelLabel element
inputInput element
errorError message
hintHint text
prefixPrefix wrapper
suffixSuffix wrapper
counterCharacter counter

Examples

With error

Errors surface automatically from the form adapter. Trigger one manually to test:

form.setError('email', { message: 'Enter a valid email address' })

<TextField name="email" label="Email" type="email" />

With hint

<TextField
  name="username"
  label="Username"
  hint="3–20 characters, letters and numbers only."
/>

With character counter

<TextField
  name="bio"
  label="Bio"
  maxLength={160}
  showCount
/>

With slot override

Replace the Label slot with a custom component. Slot components receive only display-level props.

import type { LabelSlotProps } from '@stackform/ui'

function UpperLabel({ htmlFor, children, required }: LabelSlotProps) {
  return (
    <label htmlFor={htmlFor} className="text-xs font-bold uppercase tracking-widest">
      {children}
      {required ? <span aria-hidden="true"> *</span> : null}
    </label>
  )
}

<TextField
  name="email"
  label="Email"
  slots={{ Label: UpperLabel }}
/>