+234 Design System

Forms

Field colours and metrics. Thirty-four files use an input today and there is no shared field component, so this is the largest unowned surface in the frontend.

What this replaces

The frontend has 34 files containing an <input>, 18 with a <form>, 7 with a <select> and 5 with a <textarea>, and no shared field component anywhere. Search, newsletter, contact, feedback, login, register, reset, settings and the two calculators each style their own controls.

These are the tokens that come first. The field component itself lands with the forms wave, but nothing should be built against ad-hoc values in the meantime.

Colours

--p234-color-field-bg
#ffffff/#1c1c1a1.00:1

Input, select and textarea background.

--p234-color-field-border
#8c887e/#6b685f3.54:1

Resting border. Non-text, needs 3:1, which is what makes the control visible at all.

--p234-color-field-border-hover
#5b584f/#9b978d7.11:1
--p234-color-field-ink-placeholder
#6e6b62/#9b978d5.33:1

Placeholder text. Still 4.5:1, because a placeholder nobody can read is not a hint.

--p234-color-field-bg-disabled
#f1eee7/#2424211.16:1

Two of these carry a specific obligation. field-border is checked at 3:1 against the page, which is what makes an empty control visible at all; a hairline at 1.5:1 is a box sighted readers find and nobody else does. field-ink-placeholder is checked at 4.5:1 against the field, because a placeholder nobody can read is not a hint.

Metrics

--p234-field-height2.75rem44px, the touch target floor. Most readers are on a phone.
--p234-field-padding-x0.75rem
--p234-field-radius4pxradius.md. Form controls are the one place a visible radius helps, because it separates the control from the rule grid.
--p234-field-border-width1px
--p234-field-border-width-invalid2pxAn invalid field thickens its border as well as changing colour, so the state is not carried by colour alone.

field.height is 44px and a test fails the build below that. Most readers are on a phone, and a control that needs a careful tap is a control that gets missed.

Validation is never colour alone

An invalid field changes colour and thickens its border, from 1px to 2px, and carries a message in text. A test asserts the two widths differ, so the colour-only version cannot ship by accident.

Resting, focused, invalid, disabled

Enter an email address in the form you@example.com

Tab through these to see the shared focus ring, and switch themes to check both.

HTML
<div style="display:grid;gap:var(--p234-space-5);max-width:24rem">
  <label style="display:block">
    <span style="display:block;font-family:var(--p234-type-ui-sm-family);font-size:var(--p234-type-ui-sm-size);font-weight:600;margin-bottom:var(--p234-space-3)">Email address</span>
    <input type="email" placeholder="you@example.com" style="width:100%;height:var(--p234-field-height);padding:0 var(--p234-field-padding-x);background:var(--p234-color-field-bg);color:var(--p234-color-ink);border:var(--p234-field-border-width) solid var(--p234-color-field-border);border-radius:var(--p234-field-radius);font-family:var(--p234-type-ui-family);font-size:var(--p234-type-ui-size)">
  </label>

  <label style="display:block">
    <span style="display:block;font-family:var(--p234-type-ui-sm-family);font-size:var(--p234-type-ui-sm-size);font-weight:600;margin-bottom:var(--p234-space-3)">State</span>
    <select style="width:100%;height:var(--p234-field-height);padding:0 var(--p234-field-padding-x);background:var(--p234-color-field-bg);color:var(--p234-color-ink);border:var(--p234-field-border-width) solid var(--p234-color-field-border);border-radius:var(--p234-field-radius);font-family:var(--p234-type-ui-family);font-size:var(--p234-type-ui-size)">
      <option>Lagos</option><option>Abuja</option><option>Kano</option>
    </select>
  </label>

  <div>
    <label style="display:block">
      <span style="display:block;font-family:var(--p234-type-ui-sm-family);font-size:var(--p234-type-ui-sm-size);font-weight:600;margin-bottom:var(--p234-space-3)">Email address</span>
      <input type="email" value="not-an-address" aria-invalid="true" aria-describedby="err" style="width:100%;height:var(--p234-field-height);padding:0 var(--p234-field-padding-x);background:var(--p234-color-field-bg);color:var(--p234-color-ink);border:var(--p234-field-border-width-invalid) solid var(--p234-color-error);border-radius:var(--p234-field-radius);font-family:var(--p234-type-ui-family);font-size:var(--p234-type-ui-size)">
    </label>
    <p id="err" style="font-family:var(--p234-type-meta-family);font-size:var(--p234-type-meta-size);color:var(--p234-color-error);margin:var(--p234-space-3) 0 0">Enter an email address in the form you@example.com</p>
  </div>

  <label style="display:block">
    <span style="display:block;font-family:var(--p234-type-ui-sm-family);font-size:var(--p234-type-ui-sm-size);font-weight:600;margin-bottom:var(--p234-space-3);color:var(--p234-color-ink-muted)">Country (set by your plan)</span>
    <input value="Nigeria" disabled style="width:100%;height:var(--p234-field-height);padding:0 var(--p234-field-padding-x);background:var(--p234-color-field-bg-disabled);color:var(--p234-color-ink-muted);border:var(--p234-field-border-width) solid var(--p234-color-rule);border-radius:var(--p234-field-radius);font-family:var(--p234-type-ui-family);font-size:var(--p234-type-ui-size)">
  </label>
</div>
<p style="font-family:var(--p234-type-caption-family);font-size:var(--p234-type-caption-size);color:var(--p234-color-ink-subtle);margin-top:var(--p234-space-5)">Tab through these to see the shared focus ring, and switch themes to check both.</p>

Rules