Skip to content
weftGitHub

Field

The frame every field shares: label, icon, hint, error. Wrap your own control in it.

SourcePackage @weft-js/warpPlayground

Preview

tsx
import { Input, Stack } from '@weft-js/warp'export function Anatomy() {  return (    <Stack gap="group">      <Input label="Domain" icon="globe" prefix="https://" suffix=".weft.dev" hint="You can add your own later." defaultValue="storefront" clearable />      <Input label="Release name" hint="Shown in the deploy list." counter={40} defaultValue="Autumn sale" />    </Stack>  )}

Installation

npm install @weft-js/warp

Usage

tsx
import { Field } from '@weft-js/warp'<Stack gap="group">  <Input label="Domain" icon="globe" prefix="https://" suffix=".weft.dev" hint="You can add your own later." defaultValue="storefront" clearable />  <Input label="Release name" hint="Shown in the deploy list." counter={40} defaultValue="Autumn sale" /></Stack>

Variants

Use variant to put the label on the border, which is the default, or classic to put it above the field.

tsx
import { Grid, Input } from '@weft-js/warp'export function LabelStyles() {  return (    <Grid cols={2} gap="group">      <Input label="Project name" hint="Floats on the border." />      <Input label="Project name" hint="Sits above the field." variant="classic" />    </Grid>  )}

Validation

An error takes the hint's place, so the layout doesn't jump.

tsx
import { Input, Stack } from '@weft-js/warp'export function Error() {  return (    <Stack gap="group">      <Input label="Project name" hint="Lowercase letters and dashes." defaultValue="storefront" />      <Input label="Project name" hint="Lowercase letters and dashes." defaultValue="Store Front" error="That name has a space in it." />    </Stack>  )}

An action on the edge

Input takes every Field prop, so end adds to the right edge.

tsx
import { state } from '@weft-js/core'import { Button, Input } from '@weft-js/warp'export function CustomControl() {  const token = state('tsl_4f9c2e71')  const rotate = () => (token.value = `tsl_${Math.random().toString(16).slice(2, 10)}`)  return (    <Input      label="Deploy token"      hint="Rotating it stops the old one straight away."      end={<Button size="sm" emphasis="ghost" tone="neutral" onClick={rotate}>Rotate</Button>}      value={token.value}      readonly    />  )}

With form

Fields stack into a form, and autocomplete lets the browser fill in the name and email.

tsx
import { Input, Stack, Textarea } from '@weft-js/warp'export function Form() {  return (    <Stack gap="group">      <Input label="Name" autocomplete="name" defaultValue="Mara Lindqvist" />      <Input label="Work email" type="email" autocomplete="email" defaultValue="mara@weft.dev" />      <Textarea label="About you" hint="Shown to your team." />    </Stack>  )}

When to use

Use it for

  • A control warp doesn't have that should sit with the rest of a form

Reach for something else

Playground

Variant
import { Field } from '@weft-js/warp'<Input label="Domain" hint="You can add your own later." prefix="https://" suffix=".weft.dev" />

Accessibility

  • Use the id and describedby that control receives, so the label, hint and error stay tied to your control.

API Reference

PropTypeDefaultDescription
labelstring—The name people read and screen readers announce. Always required, and it floats on the border by default.
hintunknown—A short line of help under the field.
errorunknown—Replaces the hint and marks the field invalid.
iconIconRef—An icon before the control.
prefixunknown—Fixed text before the value.
suffixunknown—Fixed text after the value.
variant"floating" | "classic"—floating puts the label on the border, classic above the field.
appearance"line"—line draws only the bottom edge.
size"sm" | "md" | "lg"—sm, md or lg. Each follows the density around it.
clearablebooleanfalseA clear button, shown once there is a value.
counternumber—The most it should hold. Draws a count under the field.
idstring—The element id. One is made for you if you leave it out.
valuestring—The current value, when you own the state.
disabledbooleanfalseCan't be focused or changed, and doesn't post with a form.
readonlybooleanfalseCan be focused, read and copied, but not changed. It still posts.
controlControl—Draws the control. Gets id, describedby, invalid and the remaining props.
endunknown—Sits at the right edge of the frame, after any suffix.
filledbooleanfalseKeeps the label up when your control holds a value the field can't see.
EventTypeDefaultDescription
onInput((e: InputEvent & { currentTarget: HTMLInputElement & HTMLTextAreaElemen…—Called on each keystroke.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="field"] [data-part="control"]

controlsweep-basesweepiconlabellabel-textlabel-charsprefixbodysuffixclearmessageerrorhintcounter

RelatedInputSelectTextarea