Text input

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.

This is the hint for the input

<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

Enter an email address in the correct format, like name@example.com

<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.

This input is two_chars wide

This input is four_chars wide

This input is eight_chars wide

This input is sixteen_chars wide

<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

This input has type 'password'

<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 &#39;password&#39;</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 label associated with the input element.
  • Use the correct input type so the purpose of each input field can be determined.
  • When collecting information about a user, use the autocomplete attribute 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=number and inputmode=numeric on 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>
Component arguments
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" }