Text input
On this page
Use this component when you want to collect textual or numerical data from a user that is not more than a single line.
Examples
Default
<form action="/" accept-charset="UTF-8" method="post">
<div class="cads-form-field">
<div class="cads-form-field__content"><label class="cads-form-field__label" id="forms_text_field_text_field-label" for="forms_text_field_text_field-input">Example text field <span class="cads-form-field__optional">(optional)</span></label><input class="cads-input" id="forms_text_field_text_field-input" aria-required="false" aria-invalid="false" type="text" name="forms_text_field[text_field]" /></div>
</div>
</form>
<%= form_with model: Forms::TextField.new, url: "/" do |form| %>
<%= form.cads_text_field(:text_field) %>
<% end %>
With hint text
Use hint text for help that’s relevant to the majority of users, based on the needs of your service.
<form action="/" accept-charset="UTF-8" method="post">
<div class="cads-form-field">
<div class="cads-form-field__content"><label class="cads-form-field__label" id="forms_text_field_text_field_hint-label" for="forms_text_field_text_field_hint-input">Example text field with hint <span class="cads-form-field__optional">(optional)</span></label>
<p class="cads-form-field__hint" id="forms_text_field_text_field_hint-hint">This is the hint for the input</p>
<input class="cads-input" id="forms_text_field_text_field_hint-input" aria-required="false" aria-invalid="false" aria-describedby="forms_text_field_text_field_hint-hint" type="text" name="forms_text_field[text_field_hint]" /></div>
</div>
</form>
<%= form_with model: Forms::TextField.valid_example, url: "/" do |form| %>
<%= form.cads_text_field(:text_field_hint, hint: "This is the hint for the input") %>
<% end %>
With error message
Error messages are used to highlight where users need to change information. They’re used together with an error summary
<form action="/" accept-charset="UTF-8" method="post">
<div class="cads-form-field cads-form-field--has-error">
<div class="cads-form-field__error-marker"></div>
<div class="cads-form-field__content"><label class="cads-form-field__label" id="forms_text_field_text_field_email-label" for="forms_text_field_text_field_email-input">Email address </label>
<p class="cads-form-field__error-message" id="forms_text_field_text_field_email-error">Enter an email address in the correct format, like name@example.com</p>
<input class="cads-input" id="forms_text_field_text_field_email-input" aria-required="true" aria-invalid="true" aria-describedby="forms_text_field_text_field_email-error" type="email" value="invalid email" name="forms_text_field[text_field_email]" /></div>
</div>
</form>
<%= form_with model: Forms::TextField.invalid_example, url: "/" do |form| %>
<%= form.cads_text_field(:text_field_email, type: :email, required: true) %>
<% end %>
Fixed widths
Help users understand the purpose of the input by making the input size appropriate for the content it’s intended for.
<form action="/" accept-charset="UTF-8" method="post">
<div class="cads-form-field">
<div class="cads-form-field__content"><label class="cads-form-field__label" id="forms_text_field_text_field_two_chars-label" for="forms_text_field_text_field_two_chars-input">Day <span class="cads-form-field__optional">(optional)</span></label>
<p class="cads-form-field__hint" id="forms_text_field_text_field_two_chars-hint">This input is two_chars wide</p>
<input class="cads-input cads-input--two-chars" id="forms_text_field_text_field_two_chars-input" aria-required="false" aria-invalid="false" aria-describedby="forms_text_field_text_field_two_chars-hint" type="text" name="forms_text_field[text_field_two_chars]" /></div>
</div>
</form>
<form action="/" accept-charset="UTF-8" method="post">
<div class="cads-form-field">
<div class="cads-form-field__content"><label class="cads-form-field__label" id="forms_text_field_text_field_four_chars-label" for="forms_text_field_text_field_four_chars-input">Year <span class="cads-form-field__optional">(optional)</span></label>
<p class="cads-form-field__hint" id="forms_text_field_text_field_four_chars-hint">This input is four_chars wide</p>
<input class="cads-input cads-input--four-chars" id="forms_text_field_text_field_four_chars-input" aria-required="false" aria-invalid="false" aria-describedby="forms_text_field_text_field_four_chars-hint" type="text" name="forms_text_field[text_field_four_chars]" /></div>
</div>
</form>
<form action="/" accept-charset="UTF-8" method="post">
<div class="cads-form-field">
<div class="cads-form-field__content"><label class="cads-form-field__label" id="forms_text_field_text_field_eight_chars-label" for="forms_text_field_text_field_eight_chars-input">Postcode <span class="cads-form-field__optional">(optional)</span></label>
<p class="cads-form-field__hint" id="forms_text_field_text_field_eight_chars-hint">This input is eight_chars wide</p>
<input class="cads-input cads-input--eight-chars" id="forms_text_field_text_field_eight_chars-input" aria-required="false" aria-invalid="false" aria-describedby="forms_text_field_text_field_eight_chars-hint" type="text" name="forms_text_field[text_field_eight_chars]" /></div>
</div>
</form>
<form action="/" accept-charset="UTF-8" method="post">
<div class="cads-form-field">
<div class="cads-form-field__content"><label class="cads-form-field__label" id="forms_text_field_text_field_sixteen_chars-label" for="forms_text_field_text_field_sixteen_chars-input">Phone number <span class="cads-form-field__optional">(optional)</span></label>
<p class="cads-form-field__hint" id="forms_text_field_text_field_sixteen_chars-hint">This input is sixteen_chars wide</p>
<input class="cads-input cads-input--sixteen-chars" id="forms_text_field_text_field_sixteen_chars-input" aria-required="false" aria-invalid="false" aria-describedby="forms_text_field_text_field_sixteen_chars-hint" type="text" name="forms_text_field[text_field_sixteen_chars]" /></div>
</div>
</form>
<%= form_with model: Forms::TextField.new, url: "/" do |form| %>
<%= form.cads_text_field(:text_field_two_chars, hint: "This input is two_chars wide", width: :two_chars) %>
<% end %>
<%= form_with model: Forms::TextField.new, url: "/" do |form| %>
<%= form.cads_text_field(:text_field_four_chars, hint: "This input is four_chars wide", width: :four_chars) %>
<% end %>
<%= form_with model: Forms::TextField.new, url: "/" do |form| %>
<%= form.cads_text_field(:text_field_eight_chars, hint: "This input is eight_chars wide", width: :eight_chars) %>
<% end %>
<%= form_with model: Forms::TextField.new, url: "/" do |form| %>
<%= form.cads_text_field(:text_field_sixteen_chars, hint: "This input is sixteen_chars wide", width: :sixteen_chars) %>
<% end %>
Page heading
<form action="/" accept-charset="UTF-8" method="post">
<div class="cads-form-field">
<div class="cads-form-field__content">
<h1 class="cads-page-title"><label id="forms_text_field_text_field_page_heading-label" for="forms_text_field_text_field_page_heading-input">Text field with page heading</label></h1>
<p class="cads-form-field__hint" id="forms_text_field_text_field_page_heading-hint">This input has type 'password'</p>
<input class="cads-input" id="forms_text_field_text_field_page_heading-input" aria-required="false" aria-invalid="false" aria-describedby="forms_text_field_text_field_page_heading-hint" type="text" name="forms_text_field[text_field_page_heading]" /></div>
</div>
</form>
<%= form_with model: Forms::TextField.valid_example, url: "/" do |form| %>
<%= form.cads_text_field(
:text_field_page_heading,
hint: "This input has type 'password'",
page_heading: true
) %>
<% end %>
Implementation
- You must always have a
labelassociated with the input element. - Use the correct input
typeso the purpose of each input field can be determined. - When collecting information about a user, use the
autocompleteattribute to help users complete forms more quickly.
Read more about input purpose at WCAG 2.1.
The following needs more research:
- The effects of
type=numberandinputmode=numericon assistive technologies? - Should we be able to group text inputs into fieldsets? Eg when capturing addresses?
Using with Rails
When using with Rails we recommend using the form builder method provided by CitizensAdviceComponents::FormBuilder.
cads_text_field(attribute, **options)
The method works similarly to the default text_field helper.
<%= form_with model: @model, url: "/" do |form| %>
<%= form.cads_text_field(:example) %>
<% end %>
With options:
<%= form_with model: @model, url: "/" do |form| %>
<%= form.cads_text_field(
:example,
hint: "Example hint",
required: true,
width: :sixteen_chars,
additional_attributes: { "data-testid": "example" }
) %>
<% end %>
The method accepts the following optional parameters:
:label- The text for the label associated with the input. Defaults to using translations.:hint- Hint text for the input:required- Boolean indicating the field is optional (i.e. not required):type- Input type. Defaults to:text:width- Predefined width, one of::two_char,:four_char,:eight_char,:sixteen_char:page_heading- Wraps the<label>in a<h1>:additional_attributes- Hash of additional attributes rendered onto the input, e.g.{ autocomplete: "name" }
View component version
We also provide an older view component version of the component
<form action="" novalidate>
<%= render CitizensAdviceComponents::TextInput.new(
name: "my-input",
label: "My input",
type: :text,
width: :sixteen_chars,
options: {
hint: "Hint text",
error_message: "Error message",
optional: true,
value: "Input value",
additional_attributes: {
"data-test-id": "test"
}
}
) %>
</form>
| Argument | Description |
|---|---|
Argument
name
|
Description Required, field name |
Argument
id
|
Description
Optional, allows customising the id. By default the id is autogenerated based on the name
|
Argument
label
|
Description Required, the text for the label associated with the input |
Argument
type
|
Description
Required, one of: :email, :hidden, :number, :password, :search, :tel, :text, :url
|
Argument
width
|
Description
Optional, one of: :two_char, :four_char, :eight_char, :sixteen_char
|
Argument
options
|
Description Optional, a hash with one or more of the following values: |
Argument
options[:page_heading]
|
Description → Optional, boolean indicating the field label is a page heading |
Argument
options[:hint]
|
Description → Optional, hint text for the input |
Argument
options[:error_message]
|
Description → Optional, an error message for the input |
Argument
options[:optional]
|
Description → Optional, boolean indicating the field is optional (i.e. not required) |
Argument
options[:value]
|
Description → Optional, the value of the input |
Argument
options[:additional_attributes]
|
Description
→ Optional, a hash of additional attributes rendered onto the input, eg { autocomplete: "name" }
|
Questions and contributions
For National Citizens Advice staff you can find us in the #design-system channel on Slack. For open issues, roadmap, and source code see the GitHub project.