Input

Input wraps the native <input>, so every DOM attribute (type, placeholder, value, onChange, disabled, aria-*) passes straight through. It is controlled iff value is set. Add a label (wired via htmlFor), a hint, or an error that swaps in error styling and aria-invalid.

Examples

Label and hint

A label is not optional in practice: a placeholder disappears the moment someone types, taking the only description of the field with it.

We only use it for deploy notifications.

Sizes and inline icon

Heights match Button (sm 32px, md 40px, lg 48px), so fields and actions line up on the same row. iconLeft sits inside the field and is decorative — it never replaces the label.

Error and disabled

error replaces hint, so a field shows one message at a time and the layout never jumps between states.

Use lowercase and dashes.

Inside a form

Validate on submit, not on every keystroke — an error that appears while someone is still typing their first character is noise. name and required are native attributes passed straight through, so the field works with FormData and with any form library.

Lowercase letters, numbers and dashes.

When to use

Use an Input for a single line of free-form text or a native typed value (email, password, number, date — set type and the platform keyboard and validation follow).

Reach for something else when:

  • The answer is more than a line — use a Textarea.
  • The answer comes from a known list — use Select for a short list, Combobox when it is long enough to need filtering.
  • It is a yes/no — use Checkbox or Switch.
  • It is a file — use FileUpload.

Accessibility

  • The label is wired to the control with htmlFor/id, so clicking it focuses the field and screen readers announce the name. An Input without a label needs an aria-label from you.
  • error sets aria-invalid and is referenced by the field, so the message is announced rather than being colour-only feedback.
  • hint and error share one slot and one id: only one is rendered at a time, so there is never a stale description pointing at the field.
  • Focus is the --shadow-focus ring; the error state changes the border, never the focus ring.

Props

NameTypeRequiredDescription
labelstringLabel rendered above the field, wired to the input via `htmlFor`.
hintstringHelper text rendered below the field. Replaced by `error` when that is set.
errorstringError message — enables the error styling (`.lyra-input--error` + `.lyra-hint--error`), sets `aria-invalid`, and replaces `hint`.
size'sm' | 'md' | 'lg'Control height. Default `"md"` (sm 32px · md 40px · lg 48px).
iconLeftReactNodeIcon rendered inside the field, on the left (e.g. `<Icon name="search" size={16} />`).

Plain HTML

The field wrapper carries the layout; the icon variant needs the extra lyra-input-wrap:

html
<div class="lyra-field">
  <label class="lyra-label" for="email">Work email</label>
  <input class="lyra-input" id="email" type="email" placeholder="[email protected]" />
  <span class="lyra-hint">We only use it for deploy notifications.</span>
</div>

<div class="lyra-field">
  <label class="lyra-label" for="slug">Workspace slug</label>
  <input class="lyra-input lyra-input--error" id="slug" aria-invalid="true" value="my workspace" />
  <span class="lyra-hint lyra-hint--error">Use lowercase and dashes.</span>
</div>