mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-12 19:50:46 +01:00
188 lines
7.6 KiB
Plaintext
188 lines
7.6 KiB
Plaintext
import { Meta, Story, Source } from "@storybook/addon-docs";
|
||
|
||
import * as formStories from "./form.stories";
|
||
import * as fieldStories from "../form-field/form-field.stories";
|
||
import * as passwordToggleStories from "../form-field/password-input-toggle.stories";
|
||
import * as searchStories from "../search/search.stories";
|
||
import * as selectStories from "../select/select.stories";
|
||
import * as multiSelectStories from "../form-field/multi-select.stories";
|
||
import * as radioStories from "../radio-button/radio-button.stories";
|
||
import * as checkboxStories from "../checkbox/checkbox.stories";
|
||
|
||
<Meta title="Component Library/Form" />
|
||
|
||
# Forms
|
||
|
||
Component Library forms should always be built using [Angular Reactive Forms][reactive]. Please read
|
||
[ADR-0001][adr-0001] for a background to this decision. In practice this means that forms should
|
||
always use the native `form` element and bind a `formGroup`.
|
||
|
||
<Story of={formStories.FullExample} />
|
||
|
||
<br />
|
||
|
||
## Form spacing and sections
|
||
|
||
Forms consists of 1 or more inputs, and ends with 1 or 2 buttons.
|
||
|
||
If there are many inputs in a form, they should be organized into sections as content relates.
|
||
**Example:** Item type form
|
||
|
||
Each input within a section should follow the following spacing guidelines (see
|
||
[Tailwind CSS spacing documentation](https://tailwindcss.com/docs/customizing-spacing)):
|
||
|
||
- 1.5rem of vertical spacing between form elements: `mb-6`
|
||
- 1.5rem of horizontal spacing between form elements: `mr-6`
|
||
- 3rem of vertical spacing below a form section: `mb-12`
|
||
- 1rem of vertical spacing between a form group divider and the group's title; so title tag has:
|
||
`my-4`
|
||
- Form section titles should be styled using `text-lg`
|
||
- Each form sections may have a single column, double or triple column layout. No form should have
|
||
more than 3 columns. Do NOT use different column layouts within the same form section. Choose the
|
||
best layout based on the number of fields and type of fields included.
|
||
|
||
## Input Types
|
||
|
||
### Field
|
||
|
||
A form field is the most common input in a form. It consists of a label, control and an optional
|
||
hint.
|
||
|
||
The styling of form fields applies to all field types: `text`, `number`, `select`, `text-area`,
|
||
`date`, etc.
|
||
|
||
Be sure to use an appropriate type attribute on fields when defining new field components (e.g.
|
||
`email` for email address or `number` for numerical information) to take advantage of newer input
|
||
controls like email verification, number selection, and more.
|
||
|
||
#### Default with required attribute
|
||
|
||
<Story of={fieldStories.Default} />
|
||
|
||
#### Password Toggle
|
||
|
||
<Story of={passwordToggleStories.Default} />
|
||
|
||
### Search
|
||
|
||
<Story of={searchStories.Default} />
|
||
|
||
### Selects
|
||
|
||
#### Searchable single select (default)
|
||
|
||
<Story of={selectStories.Default} />
|
||
|
||
#### Multi-select
|
||
|
||
<Story of={multiSelectStories.Members} />
|
||
|
||
### Radio group
|
||
|
||
Radio buttons should always be in radio groups.
|
||
|
||
Radio groups are form fields that consists of a main label and multiple radio buttons. Each radio
|
||
button consists of a label and a radio input.
|
||
|
||
The full form control + label should be selectable to allow the user a larger click target.
|
||
|
||
Radio groups should always have a default selected value.
|
||
|
||
Radio groups may optionally include extra helper text below each radio button.
|
||
|
||
If a radio group has more than 4 options and the options do not need helper text, a
|
||
[select menu](?path=/docs/component-library-form-multi-select--docs) should be used instead. Avoid
|
||
using a radio group for more than 5 options even if the options require additional explanation text.
|
||
|
||
`TODO: extend the select component to support a dropdown menu with descriptions below each option`
|
||
|
||
#### Block
|
||
|
||
<Story of={radioStories.Block} />
|
||
|
||
#### Inline
|
||
|
||
<Story of={radioStories.Inline} />
|
||
|
||
### Checkbox
|
||
|
||
The checkbox input is used to toggle an action on/off.
|
||
|
||
Checkboxes can be displayed on their own or in a group (select multiple form question). When
|
||
displayed in a group, include an input Label and any associated required/validation logic for the
|
||
field.
|
||
|
||
Unlike radio groups, checkbox groups are not required to have a default selected value.
|
||
|
||
Checkbox groups can include extra explanation text below each radio button or just the checkbox
|
||
button itself.
|
||
|
||
If a checkbox group has more than 4 options a
|
||
[multi-select components](?path=/docs/component-library-form-multi-select--docs) should be used.
|
||
|
||
#### Single checkbox
|
||
|
||
<Story of={checkboxStories.Default} />
|
||
|
||
## Accessibility
|
||
|
||
### Required Fields
|
||
|
||
- Use "(required)" in the label of each required form field styled the same as the field's helper
|
||
text (`.muted-text`).
|
||
- If whether or not a form field is required depends on another field, add this to the field's
|
||
helper text.
|
||
- **Example:** "Billing Email is required if owned by a business".
|
||
|
||
### Form Field Errors
|
||
|
||
- When a resting field is filled out, validation is triggered when the user de-focuses the field
|
||
(`onblur`). If the control is invalid, assistive technology should announce the error (consider
|
||
using `role="alert"` or an `aria-live="assertive"`).
|
||
- Validation should not be triggered if the control is left untouched; this allows a user of
|
||
assistive technology to read the entire form if they wish without triggering validation that could
|
||
interrupt them. - **TODO:** research how we might implement this behavior; as previous research
|
||
has shown Angular may not allow both validation when `dirty` `onblur` AND validation on Submit
|
||
which is a requirement
|
||
- A form control with an error should change to the error UI and the error text should be displayed
|
||
below the element and be associated to their respective fields (consider using `aria-describedby`)
|
||
- When a field with an error is focused, assistive technology should announce the label and
|
||
elements' invalid state and then the error text.
|
||
- **Example:** "URL required, Error, URL format is not acceptable."
|
||
- Once the user has re-focused the field, and starts typing. The error will disappear. Validation
|
||
should not occur when typing in most cases. Once th user unfocuses the field, validation triggers
|
||
again.
|
||
|
||
### Validation on Submit
|
||
|
||
- Validation must also occur on submit. A user may select the submit button directly without
|
||
changing focus from a form input. Or a user may disable their browser's javascript which is what
|
||
supports the inline onblur validation. Finally, there may be a server side error that can only be
|
||
checked on submit.
|
||
- On submit, a summary error should appear near the submit button or at the top of the form alerting
|
||
the user of what errors need to be addressed. This summary should be read out by assistive
|
||
technology after submit regardless of whether or not it was already on screen.
|
||
- Any invalid form control will display an inline error following the field's helper text (or in
|
||
place of)
|
||
- If submit is successful, use a success toast to alert the user of the successful action.
|
||
- For any server side errors, the Danger toast may still be used. Be sure to adjust the toast's
|
||
timeout to follow the 6 second
|
||
|
||
* 1 second for each additional 120 words rule.
|
||
|
||
### Helper Text
|
||
|
||
Similar to a field error, helper text should be associated to a field using `aria-describedby`. This
|
||
allows assistive technology to read out the instructional text and field requirements in addition to
|
||
the field’s label.
|
||
|
||
### Visual style
|
||
|
||
- All field inputs are interactive elements that must follow the WCAG graphic contrast guidelines.
|
||
Maintain a ratio of 3:1 with the form's background.
|
||
- Error styling should not rely only on using the `danger-600`color change. Use
|
||
<i class="bwi bwi-error"></i> as a prefix to highlight the text as error text versus helper
|
||
|
||
[reactive]: https://angular.io/guide/reactive-forms
|
||
[adr-0001]: https://contributing.bitwarden.com/architecture/adr/reactive-forms
|