HextaUI

Field

Labels, descriptions and errors wired to their control, with validation states and layouts for forms.

Shown on your profile.

"use client"

import { Form } from "@base-ui/react/form"
import { IconAt } from "@tabler/icons-react"

import { Button } from "@/components/ui/button"
import {
  Field,
  FieldCounter,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLabel,
  FieldStatus,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
  InputGroupTextarea,
} from "@/components/ui/input-group"

export function FieldDemo() {
  return (
    <Form
      className="w-full max-w-sm"
      onSubmit={(event) => event.preventDefault()}
    >
      <FieldGroup indicator="optional">
        <Field validationMode="onBlur">
          <FieldLabel>Display name</FieldLabel>
          <Input name="name" autoComplete="name" required />
          <FieldError match="valueMissing">
            Add the name people will see.
          </FieldError>
        </Field>
        <Field validationMode="onChange">
          <FieldLabel>Handle</FieldLabel>
          <InputGroup>
            <InputGroupInput
              name="handle"
              autoComplete="username"
              pattern="[a-z0-9_]{3,15}"
              maxLength={15}
              required
            />
            <InputGroupAddon>
              <IconAt />
            </InputGroupAddon>
            <InputGroupAddon align="inline-end">
              <FieldStatus />
            </InputGroupAddon>
          </InputGroup>
          <FieldError match="valueMissing">Pick a handle.</FieldError>
          <FieldError match="patternMismatch">
            Use 3–15 lowercase letters, numbers or underscores.
          </FieldError>
        </Field>
        <Field>
          <FieldLabel>Bio</FieldLabel>
          <InputGroup>
            <InputGroupTextarea name="bio" maxLength={160} />
          </InputGroup>
          <div className="flex items-baseline justify-between gap-3">
            <FieldDescription>Shown on your profile.</FieldDescription>
            <FieldCounter />
          </div>
        </Field>
        <Button type="submit">Save profile</Button>
      </FieldGroup>
    </Form>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/field.json

Adds the component, the HextaUI theme tokens and any HextaUI components it depends on.

import {
  Field,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
<FieldGroup indicator="optional">
  <Field>
    <FieldLabel>Email</FieldLabel>
    <Input type="email" required />
    <FieldDescription>We’ll never share it.</FieldDescription>
    <FieldError />
  </Field>
</FieldGroup>

Put any HextaUI control inside a <Field /> and it’s labelled, described and validated automatically. There’s no need to wire up id, htmlFor or aria-describedby by hand.

One control with its label, help text and validation.

Field
├── FieldLabel
├── Input / Textarea / Select / …
├── FieldDescription
├── FieldError
├── FieldCounter
└── FieldStatus

A switch or checkbox with its text beside it.

Field
├── Switch / Checkbox
└── FieldContent
    ├── FieldLabel
    └── FieldDescription

A label that wraps a whole field, so the card is the click target.

FieldLabel
└── Field
    ├── Checkbox / RadioGroupItem
    └── FieldContent
        ├── FieldTitle
        └── FieldDescription

Related fields, spaced evenly.

FieldGroup
├── Field
├── FieldSeparator
└── Field

A titled group of fields, or a radio or checkbox group with an item per option.

FieldSet
├── FieldLegend
├── FieldDescription
└── FieldGroup
    └── Field

FieldSet
├── FieldLegend
└── FieldItem
    ├── RadioGroupItem / Checkbox
    └── FieldLabel

Input

A label, a control and a description. Clicking the label focuses the input, and screen readers read the description after the label.

Shown on your profile. You can change it once a month.

import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldInput() {
  return (
    <Field className="max-w-sm">
      <FieldLabel>Username</FieldLabel>
      <Input placeholder="ada" autoComplete="username" />
      <FieldDescription>
        Shown on your profile. You can change it once a month.
      </FieldDescription>
    </Field>
  )
}

Validation

Native constraints like required and minLength are checked on blur. Give each <FieldError /> a match to word the message per problem. An empty required field is only flagged after it has been edited, so tabbing past it doesn’t shout.

At least 8 characters.

import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldValidation() {
  return (
    <Field validationMode="onBlur" className="max-w-sm">
      <FieldLabel>Password</FieldLabel>
      <Input
        type="password"
        autoComplete="new-password"
        required
        minLength={8}
      />
      <FieldDescription>At least 8 characters.</FieldDescription>
      <FieldError match="valueMissing">Choose a password.</FieldError>
      <FieldError match="tooShort">
        That’s too short. Use 8 or more characters.
      </FieldError>
    </Field>
  )
}

Custom validation

Pass validate to check anything, including async lookups. Return a message to fail or nothing to pass. With validationMode="onChange" and validationDebounceTime, it runs while typing without firing on every key. Try “ada”.

Checked as you type.

"use client"

import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

const taken = ["admin", "ada", "hexta"]

async function checkUsername(value: unknown) {
  const name = String(value ?? "")
    .trim()
    .toLowerCase()
  if (name.length === 0) {
    return null
  }
  if (!/^[a-z0-9_]+$/.test(name)) {
    return "Use letters, numbers and underscores only."
  }
  await new Promise((resolve) => setTimeout(resolve, 400))
  return taken.includes(name) ? `“${name}” is taken.` : null
}

export function FieldCustomValidation() {
  return (
    <Field
      validationMode="onChange"
      validationDebounceTime={300}
      validate={checkUsername}
      className="max-w-sm"
    >
      <FieldLabel>Username</FieldLabel>
      <Input placeholder="Try “ada”" autoComplete="off" />
      <FieldDescription>Checked as you type.</FieldDescription>
      <FieldError />
    </Field>
  )
}

Required and optional

Set indicator on a FieldGroup, FieldSet or Field and every label inside marks itself from its control's required attribute. "optional" tags the fields people can skip, which reads calmer when most fields are required. "required" adds an asterisk. The mark is hidden from screen readers because the control already announces it.

import {
  Field,
  FieldGroup,
  FieldLabel,
  FieldSeparator,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldIndicatorDemo() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-8">
      <FieldGroup indicator="optional">
        <Field>
          <FieldLabel>Email</FieldLabel>
          <Input type="email" autoComplete="email" required />
        </Field>
        <Field>
          <FieldLabel>Company</FieldLabel>
          <Input autoComplete="organization" />
        </Field>
      </FieldGroup>
      <FieldSeparator />
      <FieldGroup indicator="required">
        <Field>
          <FieldLabel>Card number</FieldLabel>
          <Input inputMode="numeric" autoComplete="cc-number" required />
        </Field>
        <Field>
          <FieldLabel>Billing note</FieldLabel>
          <Input />
        </Field>
      </FieldGroup>
    </div>
  )
}

Status

<FieldStatus /> draws a check once an edited field passes validation, and shows an alert icon while it fails. It follows the field's validationMode, so it never judges a field before validation has run.

Try HX-2026.

import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
  FieldStatus,
} from "@/components/ui/field"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@/components/ui/input-group"

export function FieldStatusDemo() {
  return (
    <Field validationMode="onChange" className="max-w-sm">
      <FieldLabel>Invite code</FieldLabel>
      <InputGroup>
        <InputGroupInput
          name="code"
          pattern="HX-[0-9]{4}"
          placeholder="HX-0000"
          autoComplete="off"
        />
        <InputGroupAddon align="inline-end">
          <FieldStatus />
        </InputGroupAddon>
      </InputGroup>
      <FieldDescription>Try HX-2026.</FieldDescription>
      <FieldError match="patternMismatch">
        Codes look like HX- followed by four digits.
      </FieldError>
    </Field>
  )
}

Character count

<FieldCounter /> finds the text control in its field and counts against its maxLength. It only listens, so typing is never slowed or changed.

Clears after 24 hours.

import {
  Field,
  FieldCounter,
  FieldDescription,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldCounterDemo() {
  return (
    <Field className="max-w-sm">
      <FieldLabel>Status</FieldLabel>
      <Input defaultValue="Shipping the field rework" maxLength={40} />
      <div className="flex items-baseline justify-between gap-3">
        <FieldDescription>Clears after 24 hours.</FieldDescription>
        <FieldCounter />
      </div>
    </Field>
  )
}

Errors from a form library or server

Pass invalid to the field and an errors array to <FieldError />. It takes the { message } shape React Hook Form and most schema libraries return. Duplicates are dropped, and several messages become a list. When the messages change, the new ones fade in and the height eases to fit, so nothing below jumps. Submit empty, then fix one rule at a time.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import {
  Field,
  FieldError,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

type Errors = {
  email?: { message: string }[]
  password?: { message: string }[]
}

export function FieldErrors() {
  const [errors, setErrors] = React.useState<Errors>({})

  return (
    <form
      className="w-full max-w-sm"
      onSubmit={(event) => {
        event.preventDefault()
        const data = new FormData(event.currentTarget)
        const password = String(data.get("password") ?? "")
        const next: Errors = {}
        if (!String(data.get("email") ?? "").includes("@")) {
          next.email = [{ message: "Enter a valid email." }]
        }
        const problems = []
        if (password.length < 8) {
          problems.push({ message: "Use at least 8 characters." })
        }
        if (!/\d/.test(password)) {
          problems.push({ message: "Include a number." })
        }
        if (problems.length > 0) {
          next.password = problems
        }
        setErrors(next)
      }}
    >
      <FieldGroup>
        <Field invalid={Boolean(errors.email)}>
          <FieldLabel>Email</FieldLabel>
          <Input name="email" autoComplete="email" />
          <FieldError errors={errors.email ?? []} />
        </Field>
        <Field invalid={Boolean(errors.password)}>
          <FieldLabel>Password</FieldLabel>
          <Input name="password" type="password" autoComplete="new-password" />
          <FieldError errors={errors.password ?? []} />
        </Field>
        <Button type="submit">Sign up</Button>
      </FieldGroup>
    </form>
  )
}

Checkboxes

Use orientation="horizontal" to put the checkbox beside its label. Inside a <FieldSet />, the legend names the whole group.

Email me about

Security alerts are always on.

import { Checkbox, CheckboxGroup } from "@/components/ui/checkbox"
import {
  Field,
  FieldDescription,
  FieldLabel,
  FieldLegend,
  FieldSet,
} from "@/components/ui/field"

const options = [
  { value: "mentions", label: "Mentions" },
  { value: "replies", label: "Replies to my comments" },
  { value: "digest", label: "Weekly digest" },
]

export function FieldCheckbox() {
  return (
    <FieldSet className="w-full max-w-sm">
      <FieldLegend variant="label">Email me about</FieldLegend>
      <FieldDescription>Security alerts are always on.</FieldDescription>
      <CheckboxGroup defaultValue={["mentions", "replies"]}>
        {options.map((option) => (
          <Field key={option.value} orientation="horizontal">
            <Checkbox name="notifications" value={option.value} />
            <FieldLabel>{option.label}</FieldLabel>
          </Field>
        ))}
      </CheckboxGroup>
    </FieldSet>
  )
}

Choice cards

Wrap a whole field in <FieldLabel /> to make the card the click target. Use <FieldTitle /> inside, since labels can’t nest. The card tints when checked and shows the focus ring when its checkbox is focused.

Add-ons
import { Checkbox } from "@/components/ui/checkbox"
import {
  Field,
  FieldContent,
  FieldDescription,
  FieldLabel,
  FieldLegend,
  FieldSet,
  FieldTitle,
} from "@/components/ui/field"

export function FieldChoiceCard() {
  return (
    <FieldSet className="w-full max-w-sm">
      <FieldLegend variant="label">Add-ons</FieldLegend>
      <div className="flex flex-col gap-3">
        <FieldLabel>
          <Field orientation="horizontal">
            <Checkbox name="backups" defaultChecked />
            <FieldContent>
              <FieldTitle>Daily backups</FieldTitle>
              <FieldDescription>
                Restore any day from the last 30.
              </FieldDescription>
            </FieldContent>
          </Field>
        </FieldLabel>
        <FieldLabel>
          <Field orientation="horizontal">
            <Checkbox name="support" />
            <FieldContent>
              <FieldTitle>Priority support</FieldTitle>
              <FieldDescription>Replies within four hours.</FieldDescription>
            </FieldContent>
          </Field>
        </FieldLabel>
        <FieldLabel>
          <Field orientation="horizontal" disabled>
            <Checkbox name="sso" />
            <FieldContent>
              <FieldTitle>Single sign-on</FieldTitle>
              <FieldDescription>
                Available on the Business plan.
              </FieldDescription>
            </FieldContent>
          </Field>
        </FieldLabel>
      </div>
    </FieldSet>
  )
}

Fieldset

<FieldSet /> groups related fields under a <FieldLegend />, which becomes the group’s accessible name. Lay fields out side by side with a plain grid.

Shipping address

Where should we send your order?

import {
  Field,
  FieldDescription,
  FieldGroup,
  FieldLabel,
  FieldLegend,
  FieldSet,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldFieldset() {
  return (
    <FieldSet className="w-full max-w-md">
      <FieldLegend>Shipping address</FieldLegend>
      <FieldDescription>Where should we send your order?</FieldDescription>
      <FieldGroup>
        <Field>
          <FieldLabel>Street address</FieldLabel>
          <Input autoComplete="street-address" />
        </Field>
        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
          <Field>
            <FieldLabel>City</FieldLabel>
            <Input autoComplete="address-level2" />
          </Field>
          <Field>
            <FieldLabel>Postal code</FieldLabel>
            <Input autoComplete="postal-code" />
          </Field>
        </div>
      </FieldGroup>
    </FieldSet>
  )
}

Responsive

orientation="responsive" stacks the label and control in narrow spaces and puts them side by side once the surrounding <FieldGroup /> is wide enough. It responds to the group’s width, not the window’s.

Shown next to your messages.

Linked from your profile.

import {
  Field,
  FieldContent,
  FieldDescription,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldResponsive() {
  return (
    <FieldGroup className="w-full max-w-xl">
      <Field orientation="responsive">
        <FieldContent>
          <FieldLabel>Display name</FieldLabel>
          <FieldDescription>Shown next to your messages.</FieldDescription>
        </FieldContent>
        <Input placeholder="Ada" className="sm:max-w-56" />
      </Field>
      <Field orientation="responsive">
        <FieldContent>
          <FieldLabel>Website</FieldLabel>
          <FieldDescription>Linked from your profile.</FieldDescription>
        </FieldContent>
        <Input placeholder="example.com" className="sm:max-w-56" />
      </Field>
    </FieldGroup>
  )
}

Disabled

Disabling a <FieldSet /> disables every field and control inside it. Pass disabled to a single <Field /> to disable just that one.

Billing details

Managed by your organization’s admin.

import { Checkbox } from "@/components/ui/checkbox"
import {
  Field,
  FieldDescription,
  FieldGroup,
  FieldLabel,
  FieldLegend,
  FieldSet,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldDisabled() {
  return (
    <FieldSet disabled className="w-full max-w-sm">
      <FieldLegend>Billing details</FieldLegend>
      <FieldDescription>Managed by your organization’s admin.</FieldDescription>
      <FieldGroup>
        <Field>
          <FieldLabel>Company</FieldLabel>
          <Input defaultValue="Acme Inc." />
        </Field>
        <Field orientation="horizontal">
          <Checkbox defaultChecked />
          <FieldLabel>Send invoices by email</FieldLabel>
        </Field>
      </FieldGroup>
    </FieldSet>
  )
}

Long content

Labels, descriptions and errors wrap inside narrow forms, including unbroken strings, and never push the layout wider.

averyveryverylongunbrokendescriptionthatmustwrapinsteadofoverflowing

This message is long on purpose and wraps onto several lines without pushing anything wider.
import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldLongContent() {
  return (
    <Field invalid className="w-72">
      <FieldLabel>
        A label long enough to wrap onto a second line in a narrow form
      </FieldLabel>
      <Input defaultValue="averyveryverylongunbrokenvaluethatkeepsgoing" />
      <FieldDescription>
        averyveryverylongunbrokendescriptionthatmustwrapinsteadofoverflowing
      </FieldDescription>
      <FieldError
        errors={[
          {
            message:
              "This message is long on purpose and wraps onto several lines without pushing anything wider.",
          },
        ]}
      />
    </Field>
  )
}

Right to left

Text, checkbox placement and error lists follow the reading direction.

سنرسل رابط التأكيد إلى هذا العنوان.

أدخل عنوان بريد صالحًا.
import { Checkbox } from "@/components/ui/checkbox"
import {
  Field,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldRtl() {
  return (
    <div dir="rtl" className="w-full max-w-sm">
      <FieldGroup>
        <Field invalid>
          <FieldLabel>البريد الإلكتروني</FieldLabel>
          <Input type="email" defaultValue="ada@" />
          <FieldDescription>
            سنرسل رابط التأكيد إلى هذا العنوان.
          </FieldDescription>
          <FieldError errors={[{ message: "أدخل عنوان بريد صالحًا." }]} />
        </Field>
        <Field orientation="horizontal">
          <Checkbox defaultChecked />
          <FieldLabel>تذكرني</FieldLabel>
        </Field>
      </FieldGroup>
    </div>
  )
}
  • The label, description and visible errors are linked to the control for you, so screen readers announce all three when it’s focused.
  • Invalid controls get aria-invalid, which also draws their error ring.
  • Errors are not live regions. They’re read when the control is focused, so validating on change doesn’t interrupt typing. On submit, move focus to the first invalid field.
  • Errors grow and fade in place instead of pushing content down. With reduced motion on, they appear without animating.

Built on the Base UI field and fieldset. Every part accepts the props of the element or primitive it renders.

PropTypeDefault
orientation
"vertical" | "horizontal" | "responsive""vertical"
indicatorMark the label from the control's required attribute. Inherited from FieldGroup or FieldSet.
"required" | "optional" | null–
nameIdentifies the field when the form is submitted.
string–
validateReturn one or more messages to fail, or nothing to pass. Async is supported.
(value, formValues) => string | string[] | null | Promise<…>–
validationMode
"onSubmit" | "onBlur" | "onChange""onSubmit"
validationDebounceTimeMilliseconds to wait between onChange validations.
number0
invalidSet it from a form library or server response.
boolean–
disabled
booleanfalse
dirty
boolean–
touched
boolean–
actionsRefValidate the field imperatively.
RefObject<{ validate: () => void }>–
render
ReactElement | (props, state) => ReactElement<div>
AttributeDescription
data-slot="field"Target fields in CSS.
data-orientationThe current orientation.
data-disabledPresent when the field is disabled.
data-validPresent when the field is valid.
data-invalidPresent when the field is invalid.
data-dirtyPresent once the value has changed from its initial value.
data-touchedPresent once the control has been focused and left.
data-filledPresent when the control has a value.
data-focusedPresent while the control has focus.
PropTypeDefault
nativeLabelSet false when render swaps the label for a non-label element.
booleantrue
optionalTextText shown with indicator="optional".
ReactNode"Optional"
render
ReactElement | (props, state) => ReactElement<label>
AttributeDescription
data-slot="field-label"Target labels in CSS. Outside a field it renders a plain label, which is how choice cards work.
data-disabledPresent when the field is disabled.
data-validPresent when the field is valid.
data-invalidPresent when the field is invalid.
data-dirtyPresent once the value has changed from its initial value.
data-touchedPresent once the control has been focused and left.
data-filledPresent when the control has a value.
data-focusedPresent while the control has focus.

An icon that reflects the field's validity. It's decorative, since the error message carries the meaning.

AttributeDescription
data-slot="field-status"Target the status icon in CSS.
PropTypeDefault
threshold
number10% of maxLength, at most 20
announcementMessage for screen readers when the count crosses the threshold or hits the limit.
(remaining: number) => string–
AttributeDescription
data-slot="field-counter"Target the counter in CSS.
data-state="near" | "limit"Present within the threshold, and at the limit.
PropTypeDefault
render
ReactElement | (props, state) => ReactElement<p>
AttributeDescription
data-slot="field-description"Target descriptions in CSS.
data-disabledPresent when the field is disabled.
data-validPresent when the field is valid.
data-invalidPresent when the field is invalid.
data-dirtyPresent once the value has changed from its initial value.
data-touchedPresent once the control has been focused and left.
data-filledPresent when the control has a value.
data-focusedPresent while the control has focus.
PropTypeDefault
matchShow only for this validity problem. true always shows it.
boolean | "valueMissing" | "typeMismatch" | "tooShort" | "tooLong" | "patternMismatch" | "rangeOverflow" | "rangeUnderflow" | "stepMismatch" | "badInput" | "customError" | "valid"–
errorsErrors from a form library or server. Shown when the list has a message.
Array<{ message?: string } | undefined>–
childrenDefaults to the validation message.
ReactNode–
render
ReactElement | (props, state) => ReactElement<div>
AttributeDescription
data-slot="field-error"Target errors in CSS.
data-starting-stylePresent while the error grows in.
data-ending-stylePresent while the error collapses.
data-disabledPresent when the field is disabled.
data-validPresent when the field is valid.
data-invalidPresent when the field is invalid.
data-dirtyPresent once the value has changed from its initial value.
data-touchedPresent once the control has been focused and left.
data-filledPresent when the control has a value.
data-focusedPresent while the control has focus.

Stacks a label, description and error beside a control in a horizontal field.

PropTypeDefault
render
ReactElement | (props, state) => ReactElement<div>

A label-styled title for content inside a <FieldLabel />, such as choice cards.

PropTypeDefault
render
ReactElement | (props, state) => ReactElement<div>

Spaces fields apart and is the container that responsive fields measure.

PropTypeDefault
indicatorApplies to every field inside.
"required" | "optional" | null–
render
ReactElement | (props, state) => ReactElement<div>
PropTypeDefault
indicatorApplies to every field inside.
"required" | "optional" | null–
disabledDisables every field inside.
booleanfalse
render
ReactElement | (props, state) => ReactElement<fieldset>
AttributeDescription
data-slot="field-set"Target fieldsets in CSS.
data-disabledPresent when the fieldset is disabled.
PropTypeDefault
variantlabel matches the size of a field label.
"legend" | "label""legend"
render
ReactElement | (props, state) => ReactElement<div>
AttributeDescription
data-slot="field-legend"Target legends in CSS.
data-variantThe current variant.

A <Separator /> spaced for forms, and accepts all of its props.

PropTypeDefault
childrenOptional text shown in the middle of the line.
ReactNode–
alignWhere the text sits along the line.
"start" | "center" | "end""center"
decorativeHide a plain line from screen readers when it is only visual.
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>
AttributeDescription
data-slot="field-separator"Target field separators in CSS.
data-contentPresent when the separator has text.
data-slot="separator-label"The element that wraps the text.

Wraps one checkbox or radio and its label inside a group, so each item can be disabled on its own.

PropTypeDefault
disabled
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>

Renders anything from the field’s validity state, for example a strength meter or a character counter.

PropTypeDefault
children
(state: { validity, errors, error, value }) => ReactNode–