Skip to main content
Pricing

Input

Free

The foundational single-line text input for forms. Supports placeholder text, prefix/suffix slots, and validation states (default, error, disabled). Pair with a visible label and optional helper or error text.

16 variants

State
Email address
name@example.com
Size SM
Email address
name@example.com
Size MD
Email address
name@example.com
Size LG

Variants

VariantDescriptionWhen to use
DefaultStandard text input with border and placeholder.Use for general-purpose single-line text entry — names, emails, URLs.
With Icon
With Addon
ErrorInput with red border and error message below.Use when validation fails and the user needs to correct the value.

Usage Guidelines

Do

Always associate a visible <label> with the input via htmlFor/id.

Don't

Use placeholder text as the only label — it disappears on focus.

Do

Provide placeholder text as a hint, not a replacement for the label.

Don't

Disable the input without explaining why.

Do

Show error messages below the input with aria-describedby linkage.

Don't

Rely solely on colour to indicate error state — include an error message.

Do

Use appropriate input types (email, url, tel) for built-in validation.

Don't

Code

HTML
<div class="lex-field">
  <label class="lex-label" for="email-input">Email address</label>
  <input
    id="email-input"
    class="lex-input"
    type="email"
    placeholder="you@example.com"
    aria-required="true"
  />
  <span class="lex-field__helper">We'll never share your email.</span>
</div>

<div class="lex-field lex-field--error">
  <label class="lex-label" for="email-error">Email address</label>
  <input
    id="email-error"
    class="lex-input lex-input--error"
    type="email"
    value="not-an-email"
    aria-invalid="true"
    aria-describedby="email-error-msg"
    aria-required="true"
  />
  <span class="lex-field__error" id="email-error-msg">
    Please enter a valid email address.
  </span>
</div>
CSS Custom Properties
.lex-input {
  width: 100%;
  height: var(--lex-input-height, 40px);
  padding: 0 var(--lex-input-padding, 12px);
  background: var(--lex-input-bg);
  border: 1px solid var(--lex-input-border);
  border-radius: var(--lex-input-radius, var(--lex-radius-md));
  color: var(--lex-input-text);
  font-size: var(--lex-font-size-sm);
  transition: border-color 150ms ease, box-shadow 150ms ease;
}

.lex-input::placeholder {
  color: var(--lex-input-placeholder);
}

.lex-input:focus {
  outline: none;
  border-color: var(--lex-input-border-focus);
  box-shadow: 0 0 0 2px var(--lex-input-ring);
}

.lex-input--error {
  border-color: var(--lex-input-border-error);
}

.lex-input--error:focus {
  box-shadow: 0 0 0 2px var(--lex-input-ring-error);
}

.lex-input:disabled {
  background: var(--lex-input-bg-disabled);
  color: var(--lex-input-text-disabled);
  cursor: not-allowed;
}
React
// Using Lexicon CSS classes with React
export function EmailField() {
  return (
    <div className="lex-field">
      <label className="lex-label" htmlFor="email">Email address</label>
      <input
        className="lex-input lex-input--md"
        id="email"
        type="email"
        placeholder="you@example.com"
        required
      />
      <p className="lex-helper-text">We'll never share your email.</p>
    </div>
  );
}

Design Tokens

TokenValue (dark)Value (light)CSS property
--lex-input-bgbg
--lex-input-borderborder
--lex-input-border-focusfocus
--lex-input-radiusradius
--lex-input-paddingpadding
--lex-input-font-sizesize
--lex-input-placeholder-colorcolor

Accessibility

  • Every input must have an associated <label> using htmlFor/id or wrapping the input.
  • Error state uses aria-invalid="true" and aria-describedby pointing to the error message element.
  • Required fields use aria-required="true" in addition to the required attribute.
  • Focus ring must be visible with at least 3:1 contrast against the background.
  • Placeholder text must not be the sole label — it is not reliably announced by all screen readers.

Keyboard Interactions

TabMoves focus into or out of the input.
Any characterTypes the character into the input.
Ctrl+A/Cmd+ASelects all text in the input.