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
namestringyes—Field name. Used as the form state key and to derive element IDs.
labelstring—Label text rendered above the input.
hintstring—Helper text shown below the input when no error is present.
placeholderstring—Placeholder 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.
maxLengthnumber—Maximum character count. Required when showCount is true.
showCountbooleanfalseShows a character counter. Requires maxLength.
prefixReactNode—Content rendered before the input (e.g. an icon).
suffixReactNode—Content rendered after the input (e.g. a currency symbol).
classNamesTextFieldClassNames—Tailwind class overrides per slot. Stacks with provider and core classes.
slotsTextFieldSlots—Component 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) => void—Called 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 }}
/>