Forms

Spacing preview

All props set. Use this to evaluate label, description, input, and message spacing together.

Link text

Supporting description text.

Validation message text.

Validation message text.

Validation message text.

<Stack space="large">
<TextField
id="sp-full"
label="Label"
secondaryLabel="Optional"
description="Supporting description text."
message="Validation message text."
value="Value"
reserveMessageSpace={true}>
<TextLink
slot="tertiaryLabel"
href="#">
Link text
</TextLink>
</TextField>
<TextField
id="sp-no-desc"
label="Label"
secondaryLabel="Optional"
message="Validation message text."
value="Value"
reserveMessageSpace={true}
/>
<TextField
id="sp-minimal"
label="Label"
message="Validation message text."
value="Value"
reserveMessageSpace={true}
/>
</Stack>

FieldLabel

Label element with optional secondaryLabel, description, and tertiaryLabel slot. secondaryLabel renders inline at secondary tone to signal it is supplementary. description renders below the label at neutral tone, small size. The tertiaryLabel slot renders a TextLink right-aligned on the label row.

Supporting description text.

Supporting description text.

Link text
<Stack space="large">
<FieldLabel label="Label" />
<FieldLabel
label="Label"
secondaryLabel="Optional"
/>
<FieldLabel
label="Label"
secondaryLabel="Required"
description="Supporting description text."
/>
<FieldLabel
label="Label"
description="Supporting description text."
disabled
/>
<FieldLabel
label="Label"
secondaryLabel="Optional">
<TextLink
slot="tertiaryLabel"
href="#">
Link text
</TextLink>
</FieldLabel>
</Stack>

FieldMessage

Renders below a field. When no message is present the element renders a non-breaking space to hold its line height. Neutral tone renders at neutral foreground. Validation tones (critical, positive, caution, info) render at their respective colours.

Neutral message (default tone, secondary text colour)

Critical: please correct this field

Positive: looks good

Caution: double-check this value

Info: this field is optional

↑ No message prop. Non-breaking space holds the line height

<Stack space="small">
<FieldMessage message="Neutral message (default tone, secondary text colour)" />
<FieldMessage
tone="critical"
message="Critical: please correct this field"
/>
<FieldMessage
tone="positive"
message="Positive: looks good"
/>
<FieldMessage
tone="caution"
message="Caution: double-check this value"
/>
<FieldMessage
tone="info"
message="Info: this field is optional"
/>
<Box>
<FieldMessage />
<Text
element="p"
tone="secondary"
size="x-small">
↑ No message prop. Non-breaking space holds the line height
</Text>
</Box>
</Stack>

Labeled fields

Pass label, secondaryLabel, and description directly to TextField, TextArea, or NumberField. FieldLabel and FieldMessage are composed automatically.

Supporting description text.

Supporting description text.

<Stack space="large">
<TextField
id="lf-a"
label="Label"
placeholder="Placeholder"
/>
<TextField
id="lf-b"
label="Label"
secondaryLabel="Optional"
placeholder="Placeholder"
/>
<TextField
id="lf-c"
label="Label"
secondaryLabel="Required"
description="Supporting description text."
placeholder="Placeholder"
/>
<TextArea
id="lf-d"
label="Label"
secondaryLabel="Optional"
description="Supporting description text."
rows={3}
/>
<NumberField
id="lf-e"
label="Label"
secondaryLabel="Optional"
min={0}
max={100}
/>
</Stack>

Validation tones

The tone prop controls both the border colour and the message text colour. The message element is auto-linked to the input via aria-describedby.

Default message, secondary tone text

Please enter a valid email address

Username is available

Password is weak, add special characters

URL will be validated on save

<Stack space="large">
<TextField
id="field-neutral"
label="Neutral"
message="Default message, secondary tone text"
/>
<TextField
id="field-critical"
tone="critical"
label="Critical"
value="bad@"
message="Please enter a valid email address"
/>
<TextField
id="field-positive"
tone="positive"
label="Positive"
value="lloyd"
message="Username is available"
/>
<TextField
id="field-caution"
tone="caution"
label="Caution"
value="Password123"
message="Password is weak, add special characters"
/>
<TextField
id="field-info"
tone="info"
label="Info"
value="https://lloydatkinson.net"
message="URL will be validated on save"
/>
</Stack>

reserveMessageSpace

When true, the message area always occupies its line height even when no message is present. Both fields stay the same height so layout is stable when messages appear and disappear. Defaults to false.

Default: both fields same height

This field has an error

reserveMessageSpace=false: no-message field is shorter

This field has an error

<Stack space="large">
<Stack space="x-small">
<Text
element="p"
tone="secondary"
size="x-small">
Default: both fields same height
</Text>
<Inline
space="medium"
alignY="top">
<Box
background="neutralLight"
padding="x-small"
borderRadius="md">
<TextField
id="rms-a"
label="No message"
placeholder="No message shown"
/>
</Box>
<Box
background="neutralLight"
padding="x-small"
borderRadius="md">
<TextField
id="rms-b"
tone="critical"
label="Has message"
value="invalid"
message="This field has an error"
/>
</Box>
</Inline>
</Stack>
<Stack space="x-small">
<Text
element="p"
tone="secondary"
size="x-small">
reserveMessageSpace=false: no-message field is shorter
</Text>
<Inline
space="medium"
alignY="top">
<Box
background="neutralLight"
padding="x-small"
borderRadius="md">
<TextField
id="rms-c"
label="No message"
reserveMessageSpace={false}
placeholder="No message shown"
/>
</Box>
<Box
background="neutralLight"
padding="x-small"
borderRadius="md">
<TextField
id="rms-d"
tone="critical"
label="Has message"
reserveMessageSpace={false}
value="invalid"
message="This field has an error"
/>
</Box>
</Inline>
</Stack>
</Stack>

Disabled

Label tone shifts to secondary and field background becomes neutralSoft. The disabled attribute is forwarded to the underlying input.

Supporting description text.

<Stack space="large">
<TextField
id="dis-a"
label="Label"
value="Value"
disabled
/>
<TextField
id="dis-b"
label="Label"
secondaryLabel="Optional"
description="Supporting description text."
value="Value"
disabled
/>
<TextArea
id="dis-c"
label="Label"
rows={3}
value="Value"
disabled
/>
<NumberField
id="dis-d"
label="Label"
value={5}
disabled
/>
</Stack>

Full form example

All features combined.

Get in touch

I'll reply to this address.

What would you like to talk about?

<Box
background="surface"
padding="large"
borderRadius="md"
boxShadow="borderNeutralLight">
<Stack space="large">
<Heading level="3">Get in touch</Heading>
<Tiles
columns={{ mobile: 1, tablet: 2 }}
space="large">
<TextField
id="form-firstname"
label="First name"
secondaryLabel="Required"
placeholder="Lloyd"
/>
<TextField
id="form-lastname"
label="Last name"
secondaryLabel="Required"
placeholder="Atkinson"
/>
</Tiles>
<TextField
id="form-email"
type="email"
label="Email"
secondaryLabel="Required"
description="I'll reply to this address."
placeholder="you@example.com"
/>
<TextArea
id="form-message"
label="Message"
secondaryLabel="Required"
description="What would you like to talk about?"
rows={5}
placeholder="Tell me what's on your mind..."
/>
<Inline space="small">
<Button tone="brand">Send message</Button>
<Button
variant="soft"
tone="neutral">
Cancel
</Button>
</Inline>
</Stack>
</Box>