StackForm
Components

SwitchField

Accessible toggle switch field with label, error, hint, and flexible label positioning

SwitchField renders a labeled <button role="switch"> connected to the active form adapter via context. Error and hint states surface automatically — no prop wiring needed.

Receive updates about your account.

Props

PropTypeRequiredDefaultDescription
namestringyesField name. Used as the form state key and to derive element IDs.
labelstringLabel text rendered next to the switch.
labelPosition'left' | 'right''right'Position of the label relative to the switch input.
hintstringHelper text shown below the switch when no error is present.
onLabelstring'On'Text rendered inside the switch when checked.
offLabelstring'Off'Text rendered inside the switch when unchecked.
size'sm' | 'md' | 'lg'Switch size. Applied via classNames from provider or field.
disabledbooleanfalseDisables the switch. Inherits from StackFormProvider if not set.
loadingbooleanfalseReplaces the switch with a skeleton shimmer.
requiredbooleanfalseMarks the field as required. Appends * to the label.
classNamesSwitchFieldClassNamesTailwind class overrides per slot. Stacks with provider and core classes.
slotsSwitchFieldSlotsComponent overrides per slot. First non-null wins: field → provider → default.
slotProps{ wrapper?, label?, input?, error?, hint? }Extra props passed to each slot. Field-level replaces provider-level per key.
onValueChange(value: boolean) => voidCalled after onChange with the new value.
validate(value: boolean) => string | undefined | Promise<string | undefined>Field-level validator. Runs on blur.

Slots

SlotProp interfaceDescription
WrapperWrapperSlotPropsOuter container element
LabelLabelSlotPropsLabel element
InputSwitchSlotPropsThe switch button element
ErrorErrorSlotPropsError message
HintHintSlotPropsHint/helper text

classNames

KeyApplied to
wrapperOuter container
labelLabel element
inputSwitch button element
errorError message
hintHint text

Examples

With error

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

form.setError('email-marketing', { message: 'This setting must be enabled' })

<SwitchField name="email-marketing" label="Email marketing" />

With hint

<SwitchField
  name="two-factor"
  label="Two-factor authentication"
  hint="Requires authentication with your phone when signing in."
/>

Custom on/off labels

Override the default "On" and "Off" labels with custom text:

<SwitchField
  name="theme-mode"
  label="Dark mode"
  onLabel="Dark"
  offLabel="Light"
/>

Label on the left

Position the label before the switch:

<SwitchField
  name="auto-save"
  label="Auto-save documents"
  labelPosition="left"
/>

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 BoldLabel({ htmlFor, children, required }: LabelSlotProps) {
  return (
    <label htmlFor={htmlFor} className="text-sm font-bold">
      {children}
      {required ? <span aria-hidden="true"> *</span> : null}
    </label>
  )
}

<SwitchField
  name="notifications"
  label="Enable notifications"
  slots={{ Label: BoldLabel }}
/>