Forms
Form Fields
Single input components in Shoreline don't have labels or help messages by default, in order to build a field to be used on a form you must use the Field compound components set.
Labels and help text
In order to be accessible, fields in a form should have labels, and in use cases where we want to provide more information fields must have helper text. In Shoreline you can use Label
and FieldDescription
to add those elements to a field.
<Field>
<Label>Label</Label>
<InputElement />
<FieldDescription>Short description</FieldDescription>
</Field>
Indicating error
Some fields might have error states when a value is invalid. You can use FieldError
and the error
prop in Field
to indicate a form error.
Since Field
provides context to its children components FieldError
won't be rendered when the error prop is set to false.
<Field error>
<Label>Label</Label>
<InputElement />
<FieldError>Short description</FieldError>
</Field>
State
Shoreline doesn't currently offer state management for forms, you may choose your prefered method of state handling and validation.
Controlled
Here's an example of a simple controlled form.
export function Controlled() {
const [value, setValue] = useState('')
const [error, setError] = useState(false)
let onSubmit = (e) => {
e.preventDefault()
setError(false)
if (value === ''){
setError(true)
}
// perform submit action on backend
}
return (
<Stack>
<form onSubmit={onSubmit}>
<Field error={error}>
<Label>Poem</Label>
<Textarea name="poem" value={value} onChange={setValue} />
<FieldDescription>Write a poem</FieldDescription>
<FieldError>You must write something</FieldError>
</Field>
<Button type="submit" variant="primary">
Submit
</Button>
</form>
</Stack>
)
}
Uncontrolled
export function Uncontrolled() {
return (
<Stack>
<form>
<Field>
<Label>Poem</Label>
<Textarea name="poem" />
<FieldDescription>Write a poem</FieldDescription>
</Field>
<Button type="submit" variant="primary">
Submit
</Button>
</form>
</Stack>
)
}
Examples
Examples of component structure for some common field use cases.
Text field
<Field>
<Label>Text</Label>
<Input />
<FieldDescription>Short description</FieldDescription>
<FieldError>Error Message</FieldError>
</Field>
TextArea field
<Field>
<Label>Multiline input</Label>
<Textarea />
<FieldDescription>Short description</FieldDescription>
<FieldError>Error Message</FieldError>
</Field>
TextArea with char counter
<Field>
<Label>Textarea with counter</Label>
<Textarea value={value} onChange={setValue} maxLength={120} />
<Flex justify="space-between">
<FieldDescription>Short description</FieldDescription>
<FieldCharCounter count={String(value).length} limit={120} />
</Flex>
<FieldError>Error Message</FieldError>
</Field>