Input
Purpose
An Input is a single-line text field that allows a user to enter or edit a freeform string value. Use it for names, search queries, URLs, email addresses, passwords, numeric strings, and other short text data. Do NOT use Input for multi-line text; use Textarea instead. Do NOT use Input when the value must be selected from a predefined list; use Select or Combobox instead.
An Input is almost always wrapped in a Field, which provides the label, description, and error message. Never render a bare Input without an associated label — even visually hidden labels are required for accessibility.
Anatomy
An Input field is composed of the following parts, managed by the Field wrapper:
- Field Label (required): a short noun phrase describing what the user should enter. Rendered as a
<label>element associated with the input. Placed above the input in vertical orientation or to the left in horizontal orientation. - Required indicator (optional): an asterisk rendered in
--force-color-text-errorimmediately after the label text. Accompanied by a screen-reader-accessible explanation at the form level ("Fields marked with * are required"). - Input wrapper: a relative-positioned container holding the input element and optional icons.
- Input element (required): the
<input>element itself. - Leading icon (optional): an icon placed inside the left edge of the input, overlaid on the input's padding. Use for semantic reinforcement of the field type (e.g., a search icon for a search field, a calendar icon for a date field). The icon is decorative — do not use it as an interactive element.
- Trailing icon (optional): an icon placed inside the right edge. Use for a clear/reset action icon (which must be a button), a loading spinner, a visibility toggle for password fields, or a non-interactive status indicator.
- Field Description (optional): secondary helper text placed below the input. Use to clarify format expectations, constraints, or tips. Render in
--force-color-text-tertiaryat--force-font-size-xs(12px). - Field Error (optional): validation error message placed below the input (replaces or supplements the description when in error state). Render in
--force-color-text-errorat--force-font-size-xs. The error container must haverole="alert"so screen readers announce it immediately.
Variants
outline (default)
The standard input style. White background (--force-color-bg-surface) with a --force-color-border-default border, rounded corners (--force-radius-input, 6px). Use this variant in all standard form layouts on white or light grey surfaces. This is the correct choice in 95% of cases.
filledDarker
A filled variant using --force-color-bg-muted as the resting background. Use when the input sits on a white surface and you want the field to read as a distinct filled zone rather than a bordered box — for example, in inline search bars or compact filter panels. The border is still present.
filledLighter
A filled variant using the standard surface background (neutral-0), functionally similar to outline. Use when a surrounding component provides the visual border context and you want the input itself to look flush. Rare; prefer outline unless you have a specific layout reason.
underline
Renders only a bottom border — no side or top borders, no rounded corners. Use in contexts where a stripped-down, low-chrome aesthetic is appropriate, such as inline editing within a dense table cell or inside a modal search bar. Do NOT use underline as the default form input style — it has lower affordance than the outline variant.
States
Default: Input is at rest, ready for typing. Border is --force-color-border-default. Background is --force-color-bg-surface (outline/filledLighter) or --force-color-bg-muted (filledDarker).
Hover: Border darkens to --force-color-border-strong (neutral-300). Background does not change for outline or filledLighter variants. For filledDarker, the background transitions from --force-color-bg-muted to --force-color-bg-emphasis. Transition at --force-duration-fast (150ms).
Focus: The input has received keyboard or programmatic focus. Border changes to --force-color-border-focus (indigo-500). A 3px spread focus ring is applied via --force-shadow-focus-ring (indigo-100). The visible indicator MUST meet WCAG 2.1 AA requirements (3:1 contrast ratio against adjacent colors). Do NOT remove the focus ring.
Filled (has value): Visually identical to default. The value text renders in --force-color-text-primary.
Placeholder: Placeholder text renders in --force-color-text-disabled (neutral-400). Placeholder text is NOT a substitute for a label. Use placeholder text only to show an example value or format hint (e.g., "e.g. john@example.com").
Read-only: The input's value is visible but cannot be edited. Apply --force-color-bg-muted background and --force-color-border-default border, with text in --force-color-text-secondary. The cursor should be default, not text.
Disabled: The entire Field (label + input + helper text) is non-interactive. Apply opacity: --force-opacity-disabled (0.5) to the outer Field container. Set the native disabled attribute on the input element. Background is --force-color-bg-muted, text is --force-color-text-disabled, cursor is not-allowed.
Error (invalid): The input has a validation error. Border changes to --force-color-border-error (cranberry-500). When the error state input is also focused, apply --force-shadow-focus-ring-error (cranberry-100 spread) instead of the standard focus ring. The Field Error message appears below the input. Set aria-invalid="true" on the input element and aria-describedby pointing to the error message element.
Loading: Show a Spinner in the trailing icon position to indicate that the field's value is being validated asynchronously. The input remains editable unless also set to read-only.
Behavior
- Sizes:
small(32px height, 8px horizontal padding),medium(40px height, 10px horizontal padding, default),large(48px height, 12px horizontal padding). Font size is 14px for small and medium, 16px for large. - Width: The input stretches to fill its container by default (
width: 100%). Use a wrapping layout (grid column, flex child with constrained width) to control width rather than setting a fixed pixel width on the input itself. - Shape: Default is
rounded(6px radius).square(no radius) andcircular(full pill) are available but are rarely appropriate for text inputs. - Icons: When a leading icon is present, increase the input's left padding to accommodate it (32px left padding). When a trailing icon is present, increase right padding similarly. The icon size is 16px and its color is
--force-color-text-disabledfor decorative icons. - Trailing clear button: When a trailing icon functions as a "clear" action, it MUST be a
<button>element witharia-label="Clear", not a plain icon. It should only appear when the input has a non-empty value. - Password visibility toggle: The trailing toggle button switches
type="password"totype="text". Usearia-label="Show password"/aria-label="Hide password"dynamically. - Keyboard: Standard browser input keyboard behavior applies. Do not intercept Tab (except to implement a custom tag/token input pattern), Enter (except when the input is the only field in a single-field search form), or Escape (except to clear a search/filter field).
- Auto-complete: Set the
autocompleteattribute appropriately (e.g.,autocomplete="email",autocomplete="new-password") to enable browser and password manager assistance.
Accessibility
- Every Input MUST have a visible
<label>(or anaria-label/aria-labelledbywhen a visible label is not feasible). Placeholder text is NOT a label replacement. - Associate the label with the input via
htmlFor/idpairing, or by nesting the input inside the label element. - Associate helper text and error messages with the input via
aria-describedby. When both are present, list both element IDs:aria-describedby="field-description field-error". - Set
aria-invalid="true"when the field is in error state. Screen readers will announce the field as invalid when focused. - The Field Error container MUST have
role="alert"so that validation errors surfaced after a form submission attempt are announced without requiring the user to re-focus the field. - Required fields: set
aria-required="true"(or the nativerequiredattribute) on the input. Announce the requirement in the label (asterisk + form-level legend explaining the asterisk convention). - For search inputs, use
type="search"and consider addingrole="searchbox"within arole="search"landmark region. - Minimum touch target for the input itself is 40px height (medium size). Do not reduce below 32px (small size) on touch surfaces.
Composition
- An Input is almost always contained within a Field component, which provides the label, description, error, and spacing.
- Multiple Fields are contained within a FieldGroup or FieldSet, which manages vertical gap (28px between fields by default).
- For horizontal label/input layouts (settings panels, filter forms), use
Fieldwithorientation="horizontal". - A search Input typically appears in a ControlsBar at the top of a data table or list page, paired with filter controls and action buttons. In this context, the Input uses
type="search"with a leading search icon. - An Input with a trailing action (clear, submit) may be placed inside a Button Group or an InputAddon pattern where a Button is visually joined to the right edge of the input.
- Do NOT place an Input inside a Tooltip — inputs are interactive and cannot be tooltip triggers.
- Do NOT combine Input with Select in the same field unless building an explicit "input with unit selector" addon pattern. Keep concerns separate.
Guidance
Choose input variant by surface, not by preference:
- On a standard form page (white background): use
outline. - In a dense toolbar or control bar needing a subtle filled appearance: use
filledDarker. - In an inline editing context (table cell, modal search): consider
underline.
Validation guidance:
- Validate on blur (when the user leaves the field), not on every keystroke, unless you are providing real-time positive feedback (e.g., password strength). On-keystroke error messages are disruptive.
- Show errors after the user has interacted with the field, not on initial page load.
- When a form is submitted with errors, focus the first invalid field and show all error messages.
Implementation requirement — explicit visual properties on all form elements:
Every <input>, <select>, and <textarea> MUST have explicit CSS declarations for background, color, and border using Force UI tokens. Do NOT rely on browser defaults for any of these properties. Browsers apply their own dark-mode styles to native form elements via prefers-color-scheme: dark and host-page stylesheets. Without explicit declarations, inputs will inherit dark backgrounds and light text from the browser or host page, breaking the Force UI light theme. Set appearance: none to strip browser-native chrome, then style fully with tokens. This applies to all variants and all states — default, hover, focus, disabled, error, and read-only must each have their visual properties explicitly declared. See the Token Usage section below for the exact values.
Common mistakes to avoid:
- Do NOT leave
background,color, orborderunset on form elements — they will inherit browser/host dark-mode defaults and appear broken. - Do NOT use
placeholderas the only indication of what a field expects. Placeholders disappear on input and are not reliably read by screen readers. - Do NOT show a success state (green border) after every field a user fills in — reserve status borders for meaningful validation results.
- Do NOT render inputs without labels in production UI, even for visually obvious search bars. Always include a visually hidden label at minimum.
- Do NOT set a fixed pixel width on individual inputs. Control width via the layout grid.
Token Usage
Outline variant (default state)
- Background:
--force-color-bg-surface - Border:
1px solid --force-color-border-default - Text (value):
--force-color-text-primary - Text (placeholder):
--force-color-text-disabled - Border radius:
--force-radius-input(6px)
filledDarker variant (default state)
- Background:
--force-color-bg-muted - Border:
1px solid --force-color-border-default - Hover background:
--force-color-bg-emphasis
filledLighter variant (default state)
- Background:
--force-color-bg-surface - Border:
1px solid --force-color-border-default
Hover state
- Border:
--force-color-border-strong
Focus state
- Border:
--force-color-border-focus - Focus ring:
--force-shadow-focus-ring(0 0 0 3px, indigo-100)
Error state
- Border:
--force-color-border-error - Error focus ring:
--force-shadow-focus-ring-error(0 0 0 3px, cranberry-100)
Disabled state
- Background:
--force-color-bg-muted - Text:
--force-color-text-disabled - Border:
--force-color-border-default - Opacity (applied to entire Field):
--force-opacity-disabled(0.5)
Label
- Color:
--force-color-text-primary - Font size:
--force-font-size-sm(14px) - Font weight:
--force-font-weight-medium(500)
Helper text / description
- Color:
--force-color-text-tertiary - Font size:
--force-font-size-xs(12px)
Error message
- Color:
--force-color-text-error - Font size:
--force-font-size-xs(12px)
Required indicator
- Color:
--force-color-text-error
Leading/trailing icon
- Color:
--force-color-text-disabled(decorative) or--force-color-icon-interactive(interactive/clickable)
Transition
- Duration:
--force-duration-fast(150ms) - Easing:
--force-easing-standard