Text Field

Single-line text input with label and validation

Usage

TextField

Basic usage:


                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-default" class="Label">Label</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium">
                                                    <input type="text" id="text-field-default" name="default" placeholder="Placeholder" />
                                                  </div>
                                                </div>

Variants:

  • InputContainer--fill (default)
  • InputContainer--outline

                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-variant-fill" class="Label">Fill (default)</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium">
                                                    <input type="text" id="text-field-variant-fill" name="variantFill" placeholder="Placeholder" />
                                                  </div>
                                                </div>
                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-variant-outline" class="Label">Outline</label>
                                                  <div class="InputContainer InputContainer--outline InputContainer--medium">
                                                    <input type="text" id="text-field-variant-outline" name="variantOutline" placeholder="Placeholder" />
                                                  </div>
                                                </div>

Sizes:


                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-size-small" class="Label">Small</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--small">
                                                    <input type="text" id="text-field-size-small" name="size-small" placeholder="Placeholder" />
                                                  </div>
                                                </div>
                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-size-medium" class="Label">Medium (default)</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium">
                                                    <input type="text" id="text-field-size-medium" name="size-medium" placeholder="Placeholder" />
                                                  </div>
                                                </div>
                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-size-large" class="Label">Large</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--large">
                                                    <input type="text" id="text-field-size-large" name="size-large" placeholder="Placeholder" />
                                                  </div>
                                                </div>

Required input:


                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-required" class="Label Label--required">Label</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium">
                                                    <input type="text" id="text-field-required" name="required" placeholder="Placeholder" required />
                                                  </div>
                                                </div>

Hidden label:


                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-hidden-label" class="Label accessibility-hidden">Label</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium">
                                                    <input type="text" id="text-field-hidden-label" name="hiddenLabel" placeholder="Placeholder" />
                                                  </div>
                                                </div>

Addons

Use InputAddon inside InputContainer to render icons, text, symbols, or controls before or after the input. If an addon acts as a label, use label element with for pointing to the input id. Treat icons and symbols as decorative and include hidden text with the addon meaning:


                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-addon-search" class="Label">Search</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium">
                                                    <label class="InputAddon InputAddon--medium" for="text-field-addon-search">
                                                      <svg class="Icon" width="20" height="20" aria-hidden="true">
                                                        <use href="/assets/icons/svg/sprite.svg#search" />
                                                      </svg>
                                                      <span class="accessibility-hidden">Use search to find jobs for you</span>
                                                    </label>
                                                    <input type="text" id="text-field-addon-search" name="addonSearch" placeholder="Search" />
                                                  </div>
                                                </div>
                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-addon-clear" class="Label">Search</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium">
                                                    <input type="text" id="text-field-addon-clear" name="addonClear" placeholder="Search" value="Filled" />
                                                    <div class="InputAddon InputAddon--medium">
                                                      <button
                                                        type="button"
                                                        class="ControlButton ControlButton--medium ControlButton--symmetrical accessibility-tap-target dynamic-color-background-interactive"
                                                        aria-label="Clear"
                                                      >
                                                        <svg class="Icon" width="20" height="20" aria-hidden="true">
                                                          <use href="/assets/icons/svg/sprite.svg#close" />
                                                        </svg>
                                                      </button>
                                                    </div>
                                                  </div>
                                                </div>

Layout

TextField is fluid by default. Use parent layout components like Grid, Stack, or Container to control the component width in page layouts.

Helper Text:

To add helper text, use the HelperText component. When helper text is present, give the helper element an id and set aria-describedby on the input to that id so assistive technologies can associate the description with the field:


                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-helper-text" class="Label">Label</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium">
                                                    <input
                                                      type="text"
                                                      id="text-field-helper-text"
                                                      name="helperText"
                                                      placeholder="Placeholder"
                                                      aria-describedby="text-field-helper-text-helper-text"
                                                    />
                                                  </div>
                                                  <div class="HelperText" id="text-field-helper-text-helper-text">Helper text</div>
                                                </div>

Supported Type Attribute Values

TextField supports the following input types:

  • email
  • number
  • password
  • search
  • tel
  • text
  • url

Other meaningful values (e.g. date, file) will work but the design of the input field will not be consistent across platforms/browsers.

Input Width

There are several ways to adjust the input width:

Input Size Attribute

The size attribute is supported on inputs of the following types: email, password, tel, text, url.

This option is generally recommended for inputs with a limited value length (e.g. numeric representation of day, month, year). Supported values are 2, 3 and 4 (characters). If you need any other value or prefer using em unit instead of default ch, define a --spirit-input-container-input-width CSS custom property on the <input> element:


                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-size" class="Label">4000 (in Roman numerals)</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium">
                                                    <input type="text" size="4" id="text-field-size" name="size" placeholder="Placeholder" />
                                                  </div>
                                                </div>
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-size-em" class="Label">4000 (in Roman numerals)</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium">
                                                    <input
                                                      type="text"
                                                      size="4"
                                                      id="text-field-size-em"
                                                      name="sizeEm"
                                                      placeholder="Placeholder"
                                                      style="--spirit-input-container-input-width: 4em;"
                                                    />
                                                  </div>
                                                </div>

Grid

For other use cases (wider input or input with unknown value length), we recommend placing inputs inside the Grid component to control their width.

JavaScript Plugin for Password Toggle

TextField with type="password" can have a toggle button. When toggling don't forget to change not only the input type but also aria-checked and aria-label.

To enable password toggle, first, you need to provide Spirit JavaScript, which will handle the functionality:


                                                
                                                <script src="node_modules/@alma-oss/spirit-web/js/cjs/spirit-web.min.js" async></script>

Please consult the main README for how to include JavaScript plugins.

Then you need to add data attribute data-spirit-toggle="password" to the input.


                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-password-toggle" class="Label">Password Toggle</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium">
                                                    <input
                                                      type="password"
                                                      id="text-field-password-toggle"
                                                      name="passwordToggle"
                                                      placeholder="Password must be at least 6 characters long"
                                                    />
                                                    <div class="InputAddon InputAddon--medium">
                                                      <button
                                                        type="button"
                                                        class="ControlButton ControlButton--medium ControlButton--symmetrical accessibility-tap-target dynamic-color-background-interactive"
                                                        role="switch"
                                                        aria-checked="false"
                                                        aria-label="Show password"
                                                        data-spirit-toggle="password"
                                                      >
                                                        <span class="accessibility-unchecked">
                                                          <svg class="Icon" width="20" height="20" aria-hidden="true">
                                                            <use href="/assets/icons/svg/sprite.svg#visibility-on" />
                                                          </svg>
                                                        </span>
                                                        <span class="accessibility-checked">
                                                          <svg class="Icon" width="20" height="20" aria-hidden="true">
                                                            <use href="/assets/icons/svg/sprite.svg#visibility-off" />
                                                          </svg>
                                                        </span>
                                                      </button>
                                                    </div>
                                                  </div>
                                                </div>

Validation States

Validation states can be presented either by adding a CSS modifier class on InputContainer (InputContainer--success, InputContainer--warning, InputContainer--danger), or by adding a JS interaction class when controlled by JavaScript (has-success, has-warning, has-danger). See Validation state dictionary.

  • To render validation text as a list, use <ul> element inside of .ValidationText.
  • To render validation text with an icon, add <svg> icon inside of .ValidationText.

                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-success" class="Label">Label</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium InputContainer--success">
                                                    <input type="text" id="text-field-success" name="success" placeholder="Placeholder" value="Filled" />
                                                  </div>
                                                </div>
                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-warning" class="Label">Label</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium InputContainer--warning">
                                                    <input
                                                      type="text"
                                                      id="text-field-warning"
                                                      name="warningValidationText"
                                                      placeholder="Placeholder"
                                                      value="Filled"
                                                      aria-describedby="text-field-warning-validation-text"
                                                    />
                                                  </div>
                                                  <div class="ValidationText ValidationText--warning" id="text-field-warning-validation-text">Validation text</div>
                                                </div>
                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-danger" class="Label">Label</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium InputContainer--danger">
                                                    <input
                                                      type="text"
                                                      id="text-field-danger"
                                                      name="dangerValidationText"
                                                      placeholder="Placeholder"
                                                      value="Filled"
                                                      aria-describedby="text-field-danger-validation-text"
                                                    />
                                                  </div>
                                                  <div class="ValidationText ValidationText--danger" id="text-field-danger-validation-text">
                                                    <ul>
                                                      <li>Validation text</li>
                                                      <li>Second validation text</li>
                                                    </ul>
                                                  </div>
                                                </div>
                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-warning-validation-icon" class="Label">Label</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium InputContainer--warning">
                                                    <input
                                                      type="text"
                                                      id="text-field-warning-validation-icon"
                                                      name="warningValidationIcon"
                                                      placeholder="Placeholder"
                                                      value="Filled"
                                                      aria-describedby="text-field-warning-validation-icon-validation-text"
                                                    />
                                                  </div>
                                                  <div class="ValidationText ValidationText--warning" id="text-field-warning-validation-icon-validation-text">
                                                    <svg class="Icon" width="20" height="20" aria-hidden="true">
                                                      <use href="/assets/icons/svg/sprite.svg#warning" />
                                                    </svg>
                                                    <div>Validation text with icon</div>
                                                  </div>
                                                </div>

Disabled State

On top of adding the disabled attribute to the input, use the InputContainer--disabled modifier on InputContainer, or with is-disabled JS interaction class when controlled by JavaScript:


                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-disabled" class="Label">Label</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium InputContainer--disabled">
                                                    <input type="text" id="text-field-disabled" name="disabled" placeholder="Placeholder" disabled />
                                                  </div>
                                                </div>
                                                
                                                <div class="Stack Stack--spacing" style="--stack-spacing: var(--spirit-space-400);">
                                                  <label for="text-field-disabled-filled" class="Label Label--required">Label</label>
                                                  <div class="InputContainer InputContainer--fill InputContainer--medium InputContainer--disabled">
                                                    <input
                                                      type="text"
                                                      id="text-field-disabled-filled"
                                                      name="disabledFilled"
                                                      placeholder="Placeholder"
                                                      disabled
                                                      required
                                                      value="Filled"
                                                    />
                                                  </div>
                                                </div>

👉 Please note that responsive border radius is defined by design specifications.