Field

Layout and validation-state kit a form control composes into.

The layout and validation-state kit a form control composes into. PanelUI's own controls — Input, Checkbox, Switch, RadioGroup — already carry their own label, description and error slot, so a single one of them needs no wrapper at all. Field is for what doesn't fit that shape: a control paired with a label off to the side, several controls grouped under one legend, or a rule breaking a form into sections.

Installation

Field ships with the library — no separate install.

import { Field, Input, Checkbox, Switch, Button } from 'panelui-native';

Or copy the source into your project, to own and edit it:

npx panelui-cli@latest add field

Usage

<Field orientation="horizontal">
  <Field.Content>
    <Field.Title>Marketing emails</Field.Title>
    <Field.Description>Product updates, at most weekly.</Field.Description>
  </Field.Content>
  <Switch value={subscribed} onValueChange={setSubscribed} />
</Field>

Composition

<Field>
  <Field.Label>…</Field.Label>
  <Field.Description>…</Field.Description>
  <Field.Error>…</Field.Error>
</Field>

<Field.Set>
  <Field.Legend>…</Field.Legend>
  <Field>…</Field>
</Field.Set>

<Field.Group>
  <Field>…</Field>
  <Field.Separator>Or</Field.Separator>
  <Field>…</Field>
</Field.Group>
  • Field.Content — Inner column for a label and description sitting beside a control, in a horizontal Field.
  • Field.Label — A Label that reads isRequired/isInvalid/isDisabled from the enclosing Field when not set explicitly.
  • Field.Description — Helper text under the control.
  • Field.Error — One validation message, or several — pass errors for an array; it dedupes by message and lists more than one with bullets. Announced with role="alert".
  • Field.Set — Groups related fields, e.g. a block of checkboxes for one setting.
  • Field.Legend — Heading for a Field.Set.
  • Field.Group — Vertical rhythm container for stacking Field/Field.Set blocks in a form.
  • Field.Separator — A rule, with an optional centered label — Or, between two sign-in options.
  • Field.Title — Non-label heading text, for a custom card-style row.

Examples

Grouped checkboxes

Field.Legend names the group; each Checkbox keeps its own label.

<Field.Set>
  <Field.Legend>Notifications</Field.Legend>
  <Checkbox checked={email} onCheckedChange={setEmail} label="Email" />
  <Checkbox checked={sms} onCheckedChange={setSms} label="SMS" />
  <Checkbox checked={push} onCheckedChange={setPush} label="Push" />
</Field.Set>

A rule between two options

A plain Separator reads as a divider; Field.Separator reads as "or".

<Field.Group>
  <Button variant="outline" onPress={continueWithApple}>
    Continue with Apple
  </Button>
  <Field.Separator>Or</Field.Separator>
  <Input label="Email" value={email} onChangeText={setEmail} />
</Field.Group>

Manual error state

errors takes an array and drops duplicate messages — for when more than one rule can fail with the same wording.

<Field invalid={errors.length > 0}>
  <Field.Label isRequired>Username</Field.Label>
  <Input value={username} onChangeText={setUsername} />
  <Field.Error errors={errors} />
</Field>

A disabled row

disabled on the root dims the title, description and control together.

<Field orientation="horizontal" disabled={!hasPro}>
  <Field.Content>
    <Field.Title>Advanced analytics</Field.Title>
    <Field.Description>Included with the Pro plan.</Field.Description>
  </Field.Content>
  <Switch value={analyticsEnabled} onValueChange={setAnalyticsEnabled} disabled={!hasPro} />
</Field>

Variants

orientation

  • vertical (default)
  • horizontal
<Field orientation="vertical">…</Field>
<Field orientation="horizontal">…</Field>

legendVariant

  • legend
  • label
<Field legendVariant="legend">…</Field>
<Field legendVariant="label">…</Field>

API Reference

Field

PropTypeDefaultDescription
classNamestring
orientation'vertical' | 'horizontal'verticalhorizontal puts a label beside the control instead of above it.
invalidbooleanfalseMarks every Field.Label/Field.Description below as invalid.
disabledbooleanfalse
requiredbooleanfalseMarks every Field.Label below as required, same as Label's own prop.

Field.Content

PropTypeDefaultDescription
classNamestring

Field.Label

PropTypeDefaultDescription
classNamestring

Field.Error

PropTypeDefaultDescription
classNamestring
errorsArray<string | { message?: string } | null | undefined>Error messages to render, deduplicated by message. A single entry renders as plain text; more than one renders as a bulleted list, since RN has no <ul>. Prefer this over children when the messages come from a form's validation state, which is naturally an array.

Field.Set

PropTypeDefaultDescription
classNamestring

Field.Legend

PropTypeDefaultDescription
classNamestring
variant'legend' | 'label'legend reads as a section heading; label sits closer to a field label.

Field.Group

PropTypeDefaultDescription
classNamestring

Field.Separator

PropTypeDefaultDescription
classNamestring

Field.Title

PropTypeDefaultDescription
classNamestring

Every part also accepts the underlying React Native props (ViewProps or TextProps) and a className for Tailwind utilities.

Notes

When you don't need it

Input, Checkbox, Switch and RadioGroup already carry their own label, description and error slot — for a single one of those, skip Field and pass the props straight through:

<Input label="Email" description="We'll never share it." errorMessage={error} />

Reach for Field when a row doesn't fit that shape. See Form for wiring one up to real validation state.

On this page