Alpha

This is an alpha release of our documentation site. View the roadmap.

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

<div class="cads-form-field">
  <div class="cads-form-field__content">
    <label class="cads-form-field__label" id="example-input-basic-label" for="example-input-basic-input">
      Example input
    </label>
    <input type="text" id="example-input-basic-input" name="example-input-basic" aria-required="true" aria-invalid="false" class="cads-input">
  </div>
</div>
<%= render(CitizensAdviceComponents::TextInput.new(
  name: "example-input-basic",
  label: "Example input",
  type: :text
))%>

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

<div class="cads-form-field">
  <div class="cads-form-field__content">
    <label class="cads-form-field__label" id="example-input-with-hint-label" for="example-input-with-hint-input">
      Example input with hint
    </label>
    <p class="cads-form-field__hint" id="example-input-with-hint-hint" data-testid="hint-message">This is the hint for the input</p>
    <input type="text" id="example-input-with-hint-input" name="example-input-with-hint" aria-required="true" aria-invalid="false" aria-describedby="example-input-with-hint-hint" class="cads-input">
  </div>
</div>
<%= render(CitizensAdviceComponents::TextInput.new(
  name: "example-input-with-hint",
  label: "Example input with hint",
  type: :text,
  options: {
    hint: "This is the hint for the input"
  }
))%>

Optional

<div class="cads-form-field">
  <div class="cads-form-field__content">
    <label class="cads-form-field__label" id="example-input-optional-label" for="example-input-optional-input">
      Example input
      <span class="cads-form-field__optional">(optional)</span>
    </label>
    <input type="text" id="example-input-optional-input" name="example-input-optional" aria-required="false" aria-invalid="false" class="cads-input">
  </div>
</div>
<%= render(CitizensAdviceComponents::TextInput.new(
  name: "example-input-optional",
  label: "Example input",
  type: :text,
  options: {
    optional: true
  }
))%>

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

<div class="cads-form-field">
  <div class="cads-form-field__content">
    <label class="cads-form-field__label" id="example-input-fixed-width-two_chars-label" for="example-input-fixed-width-two_chars-input">
      Example input
    </label>
    <p class="cads-form-field__hint" id="example-input-fixed-width-two_chars-hint" data-testid="hint-message">This input is two_chars wide</p>
    <input type="text" id="example-input-fixed-width-two_chars-input" name="example-input-fixed-width-two_chars" aria-required="true" aria-invalid="false" aria-describedby="example-input-fixed-width-two_chars-hint" class="cads-input cads-input--two-chars">
  </div>
</div>
<div class="cads-form-field">
  <div class="cads-form-field__content">
    <label class="cads-form-field__label" id="example-input-fixed-width-four_chars-label" for="example-input-fixed-width-four_chars-input">
      Example input
    </label>
    <p class="cads-form-field__hint" id="example-input-fixed-width-four_chars-hint" data-testid="hint-message">This input is four_chars wide</p>
    <input type="text" id="example-input-fixed-width-four_chars-input" name="example-input-fixed-width-four_chars" aria-required="true" aria-invalid="false" aria-describedby="example-input-fixed-width-four_chars-hint" class="cads-input cads-input--four-chars">
  </div>
</div>
<div class="cads-form-field">
  <div class="cads-form-field__content">
    <label class="cads-form-field__label" id="example-input-fixed-width-eight_chars-label" for="example-input-fixed-width-eight_chars-input">
      Example input
    </label>
    <p class="cads-form-field__hint" id="example-input-fixed-width-eight_chars-hint" data-testid="hint-message">This input is eight_chars wide</p>
    <input type="text" id="example-input-fixed-width-eight_chars-input" name="example-input-fixed-width-eight_chars" aria-required="true" aria-invalid="false" aria-describedby="example-input-fixed-width-eight_chars-hint" class="cads-input cads-input--eight-chars">
  </div>
</div>
<div class="cads-form-field">
  <div class="cads-form-field__content">
    <label class="cads-form-field__label" id="example-input-fixed-width-sixteen_chars-label" for="example-input-fixed-width-sixteen_chars-input">
      Example input
    </label>
    <p class="cads-form-field__hint" id="example-input-fixed-width-sixteen_chars-hint" data-testid="hint-message">This input is sixteen_chars wide</p>
    <input type="text" id="example-input-fixed-width-sixteen_chars-input" name="example-input-fixed-width-sixteen_chars" aria-required="true" aria-invalid="false" aria-describedby="example-input-fixed-width-sixteen_chars-hint" class="cads-input cads-input--sixteen-chars">
  </div>
</div>
<%= render(CitizensAdviceComponents::TextInput.new(
  width: :two_chars,
  name: "example-input-fixed-width-two_chars",
  label: "Example input", type: :text,
  options: { hint: "This input is two_chars wide" }
)) %>

<%= render(CitizensAdviceComponents::TextInput.new(
  width: :four_chars,
  name: "example-input-fixed-width-four_chars",
  label: "Example input", type: :text,
  options: { hint: "This input is four_chars wide" }
)) %>

<%= render(CitizensAdviceComponents::TextInput.new(
  width: :eight_chars,
  name: "example-input-fixed-width-eight_chars",
  label: "Example input", type: :text,
  options: { hint: "This input is eight_chars wide" }
)) %>

<%= render(CitizensAdviceComponents::TextInput.new(
  width: :sixteen_chars,
  name: "example-input-fixed-width-sixteen_chars",
  label: "Example input", type: :text,
  options: { hint: "This input is sixteen_chars wide" }
)) %>

With error message

Error messages are used to highlight where users need to change information. They’re used together with an error summary

Enter a valid email address, like name@example.com

<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="example-input-error-label" for="example-input-error-input">
      Email address
    </label>
    <p class="cads-form-field__error-message" id="example-input-error-error" data-testid="error-message">
      Enter a valid email address, like name@example.com
    </p>
    <input type="text" id="example-input-error-input" name="example-input-error" aria-required="true" aria-invalid="true" aria-describedby="example-input-error-error" class="cads-input">
  </div>
</div>
<%= render(CitizensAdviceComponents::TextInput.new(
  name: "example-input-error",
  label: "Email address",
  type: :text,
  options: {
    error_message: "Enter a valid email address, like name@example.com"
  }
))%>

With value

<div class="cads-form-field">
  <div class="cads-form-field__content">
    <label class="cads-form-field__label" id="example-input-value-label" for="example-input-value-input">
      Example input
    </label>
    <input type="text" id="example-input-value-input" name="example-input-value" value="Lorem ipsum" aria-required="true" aria-invalid="false" class="cads-input">
  </div>
</div>
<%= render(CitizensAdviceComponents::TextInput.new(
  name: "example-input-value",
  label: "Example input",
  type: :text,
  options: { value: "Lorem ipsum" }
))%>

With custom type

This input has type 'password'

<div class="cads-form-field">
  <div class="cads-form-field__content">
    <label class="cads-form-field__label" id="example-input-password-label" for="example-input-password-input">
      Example input
    </label>
    <p class="cads-form-field__hint" id="example-input-password-hint" data-testid="hint-message">This input has type &#39;password&#39;</p>
    <input type="password" id="example-input-password-input" name="example-input-password" value="It&#39;s a secret" aria-required="true" aria-invalid="false" aria-describedby="example-input-password-hint" class="cads-input">
  </div>
</div>
<%= render(CitizensAdviceComponents::TextInput.new(
  name: "example-input-password",
  label: "Example input",
  type: :password,
  options: {
    value: "It's a secret",
    hint: "This input has type 'password'"
  }
))%>

With custom id

By default the id is based on the name. This can be customised by passing an id argument.

<div class="cads-form-field">
  <div class="cads-form-field__content">
    <label class="cads-form-field__label" id="test-id-label" for="test-id-input">
      Example input
    </label>
    <input type="text" id="test-id-input" name="example-input-basic[test]" aria-required="true" aria-invalid="false" class="cads-input">
  </div>
</div>
<%= render(CitizensAdviceComponents::TextInput.new(
  name: "example-input-basic[test]",
  id: "test-id",
  label: "Example input",
  type: :text
))%>

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

If you are using the citizens_advice_components gem, you can call the component from within a template using:

<%= 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"
    }
  }
))%>

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[: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" }

Additional type values

If you need access to inputs with additional type values, eg file or color, you can use the base Input view component instead. The interface is the same except you may not specify a width parameter.