o-forms has "field" elements which hold an input and information about that input, e.g. its label text. Use unique ids to associate form inputs and their labels. This is required as some assistive technologies do not support implicit labels, such as Dragon Naturally Speaking.
All form fields follow the same structure:
`` ┌— field container (.o-forms-field) —————┐ | (one of div or label) | | | | ┌ title container (.o-forms-title) ┐ | | | (group titles or | | | | individual input labels) | | | └——————————————————————————————————┘ | | | | ┌ input container (.o-forms-input) ┐ | | | (group inputs or | | | | individual inputs) | | | └——————————————————————————————————┘ | └————————————————————————————————————————┘ `
Form fields may support single input fields, such as text or select boxes. Or multiple input fields, such as check boxes or toggles. There are also a number of modifying classes to change the layout or fields, e.g. to show inputs inline with their label, or to visually display an inputs validity.
$3
Single input fields are created with a label element and class o-forms-field. All label copy is wrapped within a child o-forms-title element, and the input itself is wrapped within a child o-forms-input element.
The input and its label copy are associated since they are both within a label element. Association enables a screenreader to read out the label when the user is focused on the input. Association also means clicking the label will focus the input.
The following example shows a text input:
`html
`
For a different single input, update the input element within o-forms-input and add a matching modifier to the o-forms-input element. E.g. for a textarea input:
`diff
- + - +
`
#### Text input
To create a text input use a single input field structure, with an o-forms-input--text modifier class on the o-forms-input element and an input type of type="text".
`html
`
#### File input
To create a file input use a single input field structure, with an o-forms-input--file modifier class on the o-forms-input element and an input type of type="file".
`html
`
#### Password input
To create a password input use a single input field structure, with an o-forms-input--password modifier class on the o-forms-input element and an input type of type="password".
`html
id="password-example" type="password" name="password-example" value />
`
#### Textarea input
To create a textarea input use a single input field structure, with an o-forms-input--textarea modifier class on the o-forms-input element and a textarea input element.
`html
`
#### Select Input
To create a select input use a single input field structure, with an o-forms-input--select modifier class on the o-forms-input element and a select input element.
E.g. to create an email input use a single input field structure, with an o-forms-input--text modifier class on the o-forms-input element and an input type of type="email".
`html
`
$3
For fields which have more than one input element we must build on the single input field structure. Since each field has multiple inputs the o-forms-field element becomes a div and each input is associate with its own label element. Each form element must have a unique id attribute, and the for attribute of the label element must match the id of the form element it is associated with to meet accessibility requirements.
For example to for a group of radio buttons:
`html
>Group Title >
`
Note that to associate the field title to the group of inputs we should use a fieldset and legend element. However o-forms instead relies on a role="group" attribute along with an aria-labelledby attribute and associated id, example-group-title in the label above.
Other fields which use multiple input elements follow the same structure. E.g. for a group of checkbox inputs:
`diff
Group Title
- +
`
#### Radio inputs
##### Round radio inputs
To create a radio input use a multiple input field structure, with an o-forms-input--radio-round modifier class on the o-forms-input element and child radio input elements within labels. The id attribute of the input element must match the for attribute of the label element and they must be unique within the form.
`html
>Group Title >
`
Round radio inputs support 3 themes.
- professional: For a round radios with the FT Professional theme, set o-forms-field--professional on the field element. - professional-inverse: For round radios with the inverse FT Professional theme, set o-forms-field--professional-inverse on the field element. - ft-live: For round radios with the FT Live theme, add o-forms-field--ft-live on the field element.
For a box-like, rectangular radio button replace the o-forms-input--radio-round modifier class with o-forms-input--radio-box.
Box radio buttons may also, optionally represent a negative choose by applying the o-forms-input__label--negative modifier class to its label. This is useful for a yes/no input.
Loading states are also supported by box radio buttons. We recommend using o-forms JavaScript to add states to an existing form. However to add a state manually add an additional o-forms-input__state element with role=status and aria-label="[STATE]" attributes. In addition, add a state modifier class to the o-forms-input element, o-forms-input--saving or o-forms-input--saved.
The below example shows a box style radio button with a positive "yes" and negative "no" option. The "no" option is checked and a saved state is shown.
`html
>Group Title >
>
`
To show a state label with no text set the modifier class o-forms-input__state--icon-only on the o-forms-input__state state element. Or to use custom copy for the saving and saved states add the modifier class o-forms-input__state--custom and put your copy within the state element. However, as mentioned previously, we recommend setting a custom label using the setState JavaScript method instead of adding this markup manually.
Box radio inputs support 3 themes.
- professional: For a box radio with FT Professional theme set o-forms-field--professional on the field element. - professional-inverse: For box radio with inverse FT Professional theme set o-forms-field--professional-inverse on the field element. - ft-live: For box radios with the FT Live theme, set o-forms-field--professional-inverse on the field element.
##### Pseudo box radio inputs
Deprecated, we no longer recommend pseudo box radio inputs. These will be removed in a future major version:
Its possible to achieve the look of box style radio inputs with anchor elements instead of actual radio inputs, we call these pseudo box radio inputs. This is no longer recommended and should not be used in new projects.
Links which look like form inputs may be confusing for some users of assistive technologies, as they may be accessed or behave differently than expected. Further, unlike true o-forms radio inputs, there is no fieldset with legend to group the links. For most cases, use standard box radio inputs instead.
#### Checkbox inputs
##### Square checkbox inputs
To create a checkbox input use a multiple input field structure, with an o-forms-input--checkbox modifier class on the o-forms-input element and child checkbox input elements within labels.
`html
>Group Title >
`
To align the checkbox to the right of its label, add the o-forms-input__right class to the label element:
`diff ... - ... `
Square checkboxes also support an additional theme:
- professional: To add the Professional theme to a square checkbox, add the o-forms-field--professional modifier class to the field element. - professional-inverse: To add the inverse FT Professional theme to a square checkbox, add the o-forms-field--professional-inverse modifier class to the field element. - ft-live: To add the FT Live theme to a square checkbox, add the o-forms-field--ft-live modifier class to the field element.
##### Toggle checkbox inputs
For a toggle checkbox, replace the o-forms-input--checkbox modifier class with o-forms-input--toggle.
`html
>Group Title >
Checkbox 1
Checkbox 2
`
Toggles support 2 themes.
- inverse: For a toggle on a dark background. Set o-forms-field--inverse on the field element. - white: For a toggle on a white background. Set o-forms-field--white on the field element.
##### Checkbox inputs with description
Add descriptions to toggles / checkboxes by adding o-forms-input__label__main and o-forms-input__label__prompt span elements. These must be associated with the checkbox input using aria-labelledby and aria-describedby attributes:
`html class="o-forms-field" role="group" aria-labelledby="[your-title-id]" aria-describedby="[your-description-id]" > >Toggle inputs with description > >Optional prompt text >
id="checkbox-example" type="checkbox" name="default" value="Lorem ipsum dolor sit amet" checked="" aria-labelledby="[your-checkbox-label-id]" aria-describedby="[your-checkbox-description-id]" required="" /> Lorem ipsum dolor sit amet
id="[your-checkbox-description-id]" class="o-forms-input__label__prompt" > Lorem ipsum dolor sit amet consectetur adipisicing elit. Ad earum magnam vel possimus harum suscipit.
`
#### Date inputs
We do not use
input[type=date], but instead combine three input[type=text] inputs. We use inputmode="numeric" to show a numeric keyboard in mobile browsers which support the attribute. And use a pattern attribute for basic client side date validation.
To create our date input use a multiple input field structure, with an
o-forms-input--date modifier class on the o-forms-input element, containing inputs as shown:`html
To add additional, contextual information to an input label add a title element with class
o-forms-title__prompt. When adding a prompt to a multiple input field, such as a checkbox or radio button group, give the prompt element an id and associated aria-describedby label on the field.
For a single input field, such as a text input:
`diff Label for input here + Extra context for the input
`
For a multiple input field, such as a checkbox group:
`diff -
+
Group Title + Extra context for the input
Checkbox 1
Checkbox 2
`
$3
Add the
o-forms-field--optional class to indicate that a field is optional. For example to mark a text field as optional:`diff - + Label for input here
`
$3
To inline an element, such as a button, after an input add the class
o-forms-input--suffix on the o-forms-input element. For example to inline a button with a text input using a button:`diff Search for an example thing
- +
+
`
$3
Add the class
o-forms-input--small on the o-forms-input element to reduce the size of an input. For example to output a small text input:`diff Label for input here
- +
`
$3
#### Inline Field
To display an input next to its label, rather than below, set
o-forms-field--inline.`diff - + Label for input here
`
If the label of an inlined field is short the class
o-forms-title--vertical-center may be added to align the title element vertically with the input.`diff - + - + Label for input here
`
By default the inline label and input will be a set width to ensure multiple inline fields are aligned with one another. Set
o-forms-title--shrink to allow the input to take all available space.`diff - + - + short label
`
#### Inline Inputs
Add the class
o-forms-input--inline to the o-forms-input element to display multiple inputs inline. For example, by default multiple checkboxes are stacked on top of each other but may be shown in a row:`diff
To show a custom error message below an input add an element with class
o-forms-input__error as a child of the o-forms-input element. Add your message to o-forms-input__error and to meet accessibility standards we add role="alert".
For example to create a required text field with a custom error message, whilst including
o-forms JavaScript.`diff Label for input here
- + +
For example to render an invalid field without
o-forms JavaScript:`diff Label for input here
- + - + +
#### Error Summary
o-forms also generates an error message element when a form is submitted and invalid inputs are recognised. Inputs must have a unique id and a field title element to show in the error summary.
This feature will collect the custom messages of the invalid fields if they are present in the markup, or will default to the browsers native error message if they aren't. It will associate the message to the title of the input that is invalid, generate a list of links at the top of the form, and focus on the first link.
This markup will always be generated dynamically if the errorSummary option is not set to
false.
If you are not using
o-forms JavaScript you may manually create the error summary within an o-forms element using the following markup:`html
If you would like to be more specific about what aspects of the styles get output, then you'll need to provide the primary mixin with an
$opts map. For example, in order to output styles for text inputs and checkboxes, and add the ability to inlne them, you would use the following:`scss @import '@financial-times/o-forms/main'; @include oForms( $opts: ( 'elements': ( 'text', 'checkbox', ), 'features': ( 'inline', ), ) ); `
$3
o-forms has many options due to its comprehensive nature. The $opts map accepts two lists with the following options:
valid and invalid styles are output with the base of o-forms so there is no need to include them in the list above._
_Note 2: It's important to remember that not all features will apply to all input types. If there are any features you would like to see added to an input, please get in touch with the team._
$3
There is one public mixin to customise two types of input: pseudo radio links and [box-styled
input[type=radio]](#inputttyperadio-box). It accepts four arguments:
-
$input: (required) either 'pseudo-radio-link' or 'radio' - $modifier: (required) this will name the modifier to add to the input container class list - $icons: (optional) accepts an icon or a list of icons to output according to the custom theme - $theme: (required) a map of the colors that define the custom theme: - 'controls-base': the base color of the theme - 'controls-checked-base': the background color of a checked input - 'controls-negative-checked-background': the background color for a 'negative' checked input - 'controls-border': the colour of the border around the controls`scss @include oFormsAddCustom( ( $input: 'radio', $modifier: 'my-theme', // outputs the class 'o-forms-input--my-theme', $icons: 'burger' $theme: ( controls-base: 'claret', controls-checked-base: 'white', controls-negative-checked-background: 'claret-30', ), ) ); `
JavaScript
No code will run automatically unless you are using the Build Service. You must either construct an
o-forms object or fire an o.DOMContentLoaded event, which o-forms listens for.
The JavaScript for this component is primarily responsible for individual input validation and overall form validation.
If you would like to use an input without a form element, you can still apply validation to it with the
o-forms JavaScript has been written to identify and run on a
element.
$3
In the case where a single input is enough for a product but requires validation, you can initialise an
Input instance:`js import Input from '@financial-times/o-forms/src/js/input'; new Input(myInputEl); `
$3
o-forms offers the ability to display a 'saving' or 'saved' state. However, currently the only input that accepts state is the [box-styled input[type=radio]](#inputtyperadio-box). If you would like to apply state to any other input, please get in touch with the team.o-forms has no opinion about the timing of the states—it doesn't know when to change from 'saving' to 'saved', but it has a public method setState that allows the project to control this.
The
setState method accepts three arguments: the state, name, and label. State can be one of 'saving', 'saved' or 'none'. 'none' removes any state from the input. The name argument must be the name of the inputs that will be recieving the state. Label is used in the user interface to describe the state. Label is optional and defaults to 'Saving' for the saving state and 'Saved' for the saved state.`html
... Daily
Weekly
...
``js import oForms from '@financial-times/o-forms'; let myForm = oForms.init(); // on event, e.g. click myForm.setState('saving', 'my-radio-box'); `
To change the saving label pass a third argument, e.g. to update the label from "Saving" to "Sending":
You also have the option of displaying state as an icon without text. In order to do this, you can call the method above with an extra options argument: