Skip to content

Field

Field gives a control its label, helper text and error message. It connects them for assistive tech (for/id, aria-describedby, aria-invalid) and passes required, disabled and invalid down to the control. Input, Textarea, Select, Combobox, DatePicker and PhoneInput all read from the surrounding Field.

import { Field } from '@beyul/sulmu-ui'

Source · Figma

Include https://
import { Field, Input, Stack } from '@beyul/sulmu-ui'
export default function Example() {
return (
<Stack style={{ maxWidth: 320 }}>
<Field label="Client name" required>
<Input placeholder="Placeholder" />
</Field>
<Field label="Website" helperText="Include https://">
<Input placeholder="https://example.com" />
</Field>
</Stack>
)
}

Passing errorText marks the field invalid; there is no need to set invalid as well.

Enter a valid email address
import { Field, Input } from '@beyul/sulmu-ui'
export default function Example() {
return (
<div style={{ maxWidth: 320 }}>
<Field label="Email" required errorText="Enter a valid email address">
<Input defaultValue="contact@" />
</Field>
</div>
)
}

labelAction places a link or button at the right of the label.

import { Field, Input } from '@beyul/sulmu-ui'
export default function Example() {
return (
<div style={{ maxWidth: 320 }}>
<Field label="Password" labelAction={<a href="#forgot">Forgot password?</a>}>
<Input type="password" placeholder="Enter password" />
</Field>
</div>
)
}
import { Field, Select, Stack, Textarea } from '@beyul/sulmu-ui'
const priorities = [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
]
export default function Example() {
return (
<Stack style={{ maxWidth: 320 }}>
<Field label="Priority" required>
<Select items={priorities} defaultValue={['low']} />
</Field>
<Field label="Description">
<Textarea placeholder="What does this client do?" />
</Field>
</Stack>
)
}

The Field generates an id and uses it for the label, the control and the messages. When the input needs a known id (for tests or a password manager), give it to the Field with ids. Do not put id on the Input: the label would still point at the generated id.

The input has id="email".
import { Field, Input } from '@beyul/sulmu-ui'
export default function Example() {
return (
<div style={{ maxWidth: 320 }}>
{/* The Field owns the id: label, input and messages all use it. */}
<Field label="Email" ids={{ control: 'email' }} helperText='The input has id="email".'>
<Input type="email" placeholder="name@example.com" />
</Field>
</div>
)
}
PropTypeDefaultDescription
labelReactNode-Visible label. Clicking it focuses the control.
labelActionReactNode-Link or button on the right of the label, e.g. <a href="/forgot">Forgot password?</a>.
helperTextReactNode-Hint shown under the control.
errorTextReactNode-Error shown under the control. Passing it marks the field invalid.
children*ReactNode-The control: Input, Textarea, Select and so on.
idsElementIds-The ids of the field parts.
disabledboolean-Indicates whether the field is disabled.
invalidboolean-Indicates whether the field is invalid.
requiredboolean-Indicates whether the field is required.
readOnlyboolean-Indicates whether the field is read-only.

The remaining props of Ark UI’s Field.Root are accepted too.

  • One Field wraps one control.
  • required adds the required indicator to the label and sets required on the control.
  • Helper text and error text are linked to the control with aria-describedby.
  • Write error text that says how to fix the problem (“Enter a valid email address”).