Field

What the user types or picks in a form. The intent decides the element (<input>, <textarea>, <select>) and sets type, inputMode and autoComplete.

Renders

inputtextareaselect

Intents

Domains

Examples

A labelled field with a hint

The label is a text.label rendered as <label>. The intent sets type, inputMode and autoComplete.

Preview

Only used for signing in.

<Layout intent="layout.field" className="w-full max-w-sm">
<Text intent="text.label" as="label" htmlFor="example-email">Email</Text>
<Field intent="field.email" id="example-email" placeholder="you@example.com" aria-describedby="example-email-hint" />
<Text intent="text.caption" id="example-email-hint">Only used for signing in.</Text>
</Layout>

An error

aria-invalid marks the field; the message is a feedback.error under it.

Preview
<Layout intent="layout.field" className="w-full max-w-sm">
<Text intent="text.label" as="label" htmlFor="example-handle">Handle</Text>
<Field intent="field.text" id="example-handle" defaultValue="ada" aria-invalid aria-describedby="example-handle-error" />
<Text intent="feedback.error" id="example-handle-error">That handle is taken.</Text>
</Layout>

A list to pick from

field.select renders a <select>; the options are its children.

Preview
<Layout intent="layout.field" className="w-full max-w-sm">
<Text intent="text.label" as="label" htmlFor="example-zone">Time zone</Text>
<Field intent="field.select" id="example-zone" defaultValue="Europe/London">
<option>America/New_York</option>
<option>Europe/London</option>
<option>Asia/Tokyo</option>
</Field>
</Layout>

Several lines

field.multiline renders a <textarea>.

Preview
<Field intent="field.multiline" aria-label="Bio" rows={3} placeholder="A few words about you" width="full" />

Intents it renders

One domain, with its own page of neighbours and examples. The intent decides the element; these are the starter intents.

Field field.*

14 intents
  • field.text

    Short free text on one line: names, titles, handles

    <input type="text">
  • field.email

    An email address

    <input type="email">
  • field.password

    A password, with room for a show/hide control. Set autoComplete="new-password" when creating one

    <input type="password">
  • field.password.shown

    A password field while its content is revealed

    <input type="text">
  • field.search

    The main search of a page: find people, products, anything

    <input type="search">
  • field.filter

    Narrows a list that is already shown, usually in a toolbar: "Search this feed"

    <input type="search">
  • field.number

    A quantity or amount

    <input type="number">
  • field.range

    A value picked by sliding along a scale: volume, a playback position, a price limit. Give it min, max, value and an aria-label

    <input type="range">
  • field.url

    A full web address

    <input type="url">
  • field.multiline

    Longer free text over several lines: bios, messages, notes

    <textarea>
  • field.checkbox

    A yes/no choice that is sent with a form: remember me, agree to terms. Pair with a text.label

    <input type="checkbox">
  • field.switch

    A setting that turns on or off immediately: show images, compact mode. Pair with a text.label

    <input type="checkbox">
  • field.select

    One value from a list too long to show as options: country, time zone. Children are <option>s

    <select>
  • field.color

    Any colour, picked with the system colour picker

    <input type="color">

Props

Plus its element’s usual attributes (id, onClick, aria-*, data-*) and the shared layout props below. No className or style.

  • intent required

    What is being entered: field.email, field.password, field.multiline...

    FieldIntent
  • label

    The label. With it, Field renders the whole layout.field: label, field, hint and error, connected for screen readers.

    ReactNode
  • hint

    Help under the field (text.caption). Needs label.

    ReactNode
  • error

    What is wrong with the value (feedback.error). Marks the field invalid. Needs label.

    ReactNode
  • rows

    Height of a multiline field, in lines.

    number
  • children

    For select fields: the <option>s.

    ReactNode
  • ref

    Reaches the underlying element.

    Ref<HTMLInputElement>
  • unsafeClassName

    Bypasses the intent. Needs a // prongs-unsafe: <reason> comment on the line above, and prongs check counts it.

    string

Layout props

Where the element sits, never how it looks. Spacing between elements comes from the parent <Layout>.

  • align

    On text, the text alignment. On anything else, pushes it to that end of its row or column.

    'start' | 'center' | 'end'
  • width

    Full width, or a maximum width.

    'auto' | 'full' | 'prose' | 'sm' | 'md' | 'lg'
  • hideBelow

    Hidden on screens narrower than this breakpoint.

    'sm' | 'md' | 'lg'
  • showBelow

    Shown only on screens narrower than this breakpoint.

    'sm' | 'md' | 'lg'
  • truncate

    One line, cut off with an ellipsis.

    boolean
  • nowrap

    Keeps the text on one line.

    boolean

Rules

  • Do not pass type: the intent sets it.

  • Label it with label (plus hint and error), which renders and wires the whole field; or give it an aria-label when the label is visible elsewhere, like a search box.

  • It takes the usual input attributes: value, onChange, name, placeholder, required...