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