GitHub

Components / Form & Input / Field

Field beta

The wrapper every control deserves: a label, a hint, and an error that knows which input it belongs to.

Preview

Shown in menus and the sidebar. You can change it later.

That address is missing its domain.

Uses: Input — include its CSS alongside this one.

<div style="display:grid;gap:18px;max-width:430px">
  <div class="k-field">
    <label class="lab" for="f-name">Workspace name <span class="opt">Optional</span></label>
    <input class="input" id="f-name" type="text" value="Acme Studio" aria-describedby="f-name-hint">
    <p class="hint" id="f-name-hint">Shown in menus and the sidebar. You can change it later.</p>
  </div>
  <div class="k-field" data-invalid>
    <label class="lab" for="f-mail">Billing email <span class="req">Required</span></label>
    <input class="input" id="f-mail" type="email" value="accounts@acme" aria-describedby="f-mail-err" aria-invalid="true">
    <p class="err" id="f-mail-err"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="8.5"/><path d="m9.5 9.5 5 5m0-5-5 5"/></svg> That address is missing its domain.</p>
  </div>
</div>
.k-field{display:grid;gap:7px;font-family:var(--k-font);text-align:left}
.k-field .lab{display:flex;align-items:baseline;gap:8px;font-size:13px;font-weight:550;color:var(--k-ink)}
.k-field .req{font-size:11px;font-weight:500;color:var(--k-danger)}
.k-field .opt{font-size:11px;font-weight:500;color:var(--k-ink-3)}
.k-field .hint{font-size:12px;color:var(--k-ink-3);line-height:1.6}
.k-field .err{display:flex;gap:6px;align-items:center;font-size:12px;font-weight:500;color:var(--k-danger)}
.k-field[data-invalid] input,.k-field[data-invalid] textarea,.k-field[data-invalid] select{border-color:var(--k-danger)}

Usage

Wrap any single control in a Field so labels, hints and errors stay attached. Stack Fields with a consistent gap and a form stops looking improvised.

Accessibility

The label is a real <label>, the hint and error are wired with aria-describedby, and the error carries role="alert" only when it appears after submit — not while typing.

Related parts