Form
Open in Storybook Open in Figma
This page describes how to assemble individual inputs and labels into forms.
Rules For Accessibility
- For complex forms add instructions on top of the form to help users understand how to correctly complete the form.
- Provide instructions to help users understand how to complete individual form controls (like in which format dates should be typed in).
- Validate the user input and provide options to undo changes and confirm data entry.
- Divide long forms into multiple smaller forms that constitute a series of logical steps or stages and inform users about their progress.
Grid
Form input fields and their labels need to be placed in grids so they behave properly in all tiers.
- Use
.row
without a.container
around it to avoid the form to be indented left and right. - Use
.row.form-group
and in it two columns (label, input). - The first column is either an actual
<label>
or a fake one, depending on whether labelling the element in the second column is allowed. It must have the.col-form-label
class and a.col-*
sizing class. - The second column is a
<div>
that contains the actual input(s). It too needs.col-*
classes as usual.
Rules For Accessibility
- Each input field needs a label. Use a
<label>
tag with the ‘for’ attribute to correctly assign the label to the input. This label is not necessarily the one displayed in the first column, as e.g. a checkbox may have its label appended. - If we display read-only text instead of an input field, we must use a fake label, i.e. no
<label>
element, as there would not be an<input>
element to associate it with. - Group and associate related form controls with
<fieldset>
and<legend>
.
Single-column
In George, forms are usually single column where there is each input field (and its label) in each line. This kind of form uses ‘To-the-left’ Labels (see below).
Two-column
In some rare cases (e.g. the address book), there are two columns per line. In this case, you need to set a grid to make all input fields properly rearrange on small devices. This kind of form uses ‘Above’ Labels (see below) and requires the use of a .row.g-form-multicol
row containing two .col-*-6
columns, which then contain the individual .row.form-group
s. In these form groups, both the label and the input fields are set in using .col-12
. This nested grid is necessary to make all spacings uniform across all tiers and other kinds of forms in other cards on the same page.
Labels
‘To-the-left’ labels
In this default type of labels in forms of all kind in George.
Rules For Designers
- Labels are left-aligned and presented in semi-bold 600.
- Labels and their input field are placed using a 4-8 grid.
- Input fields fill 100% width of their cell.
- On
XS
/SM
tier, ‘To-the-left’ labels automatically turn into ‘Above’ labels.
‘Above’ labels
In this case, the label is above the input field. They are only used in two-column layouts or when ‘To-the-left’ are shown on smaller tiers:
Rules For Designers
- Labels are left-aligned with the border of the input field below.
- Input fields fill 100% width of their cell.
- Vertical spacing between label and input field is 10px.
- Vertical spacing between the input field and the following label 25px.
Spacing
There are two kinds of horizontal spacings when using forms.
The default larger spacings are fine when mixing text lines with larger input fields.
When no input fields are used, the default spacings might be too large. They can be avoided by adding the .g-form-compact
class to each row. However, those tighter spaces are incompatible with input fields and can only be used in summary pages that feature only text:
Rules For Designers
- There is a 40px spacing between regular rows (label-to-label). This results in a 16px spacing between input fields.
- There is a 20px spacing between compact rows (label-to-label).
- Too long label texts are ellipsed (…).
- Only labels and amounts are semi-bold 600.
FormField
Every Form has one or many FormFields. At the very least, a FormField comes with a label
and an input
. The input determines what the user should enter/select, and at the same time is the primary driver for the FormField’s overall look. Many props exist that change the appearance further, most notably variant
, labelColumnWidth
, and labelPosition
(in charge of the already covered label placement). And then there are boolean props like required
, disabled
, and invalid
.
It does not stop there, many more things can be configured, which when present will orbit around label and input: A description
, small alerts, an interactive addOn
, and more.
Description
This section handles optional small text below an input field that may contain help or additional information about that field:
Rules For Accessibility
- While it is tempting to think the caption is attached to the input field by providing a reference (either with the
aria-labelledby
or thearia-describedby
attribute), in this casearia-details
is used, because the content of the caption may get quite long, and rich content may be used. - Due to the use of
aria-details
, the caption has no impact on the accessible description, so it is not announced by assistive technology while the focus is on the input field. Hence the caption should not contain information that is required to know while the user is typing.
Alerts
Error messages for individual input fields (as opposed to the overall form) should be placed directly following the input field using small Alerts.
Rules For Accessibility
- Notify users about successful form completion as well as input errors.
- Use the ARIA role ‘alert’ to notify the user without them having to focus the element holding the message.
- Provide instructions to help the user correct mistakes.
- Assign the instructions to the input that caused the error by adding
aria-describedby="id-of-error-container"
to the input field.
Large variant REACT-ONLY
In the large variant of a FormField, there is a larger input box and the label can be positioned above, aside or inside it.
Rules For Designers
- The padding in a large FormField is 16px.
- The input in a large FormField is bold and it has a font-size of 40px.
- When placed inside the input, the label is semi-bold 600 and it has a font-size of 14px.
Just like regular FormFields, lthe large variant can also have a description (rich text), specified via the description
prop. However, unlike regular FormFields, the description is no longer placed underneath, but is now displayed as a small section inside the input.
Add-on REACT-ONLY
An interactive add-on can be added to a FormField, usually a Button or a Link. The visual placement of the add-on on screen is highly responsive and determined by the overall configuration of the FormField.
HINT Do not confuse FormField add-ons with InputGroup add-ons. A FormField can have an add-on, and its input can be an InputGroup that itself has add-ons. The former is always visually separated from FormField’s label and input.
Rules For Developers
- When the add-on is a Button, make it
VARIANT.TERTIARY
,SIZE.SMALL
, andFULL_WIDTH.NEVER
. - When the FormField is
disabled
, the add-on is not affected, as there may be cases when the add-on provides useful information related to the disabled control, e.g. it opens a Modal. So whenever the add-on should be disabled too, it has to be done manually. - There are two scenarios where the add-on won’t be rendered:
- in any FormField with
LABEL_POSITION.INSIDE
, and - in a large FormField with
LABEL_POSITION.ASIDE
.
- in any FormField with
Buttons
To properly group Buttons, a ButtonGroup with the modifier .g-group-button-form
should be used. This automatically sets the right margins and pulls the primary button to the first position on small devices.
Rules For Developers
- Buttons should be
SIZE.REGULAR
- Place the
VARIANT.PRIMARY
Button at the end of the ButtonGroup