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.

API and code

NameTypeRequiredDescription
labelstring—Label rendered above the field, wired to the input via `htmlFor`.
hintstring—Helper text rendered below the field. Replaced by `error` when that is set.
errorstring—Error 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).
iconLeftReactNode—Icon rendered inside the field, on the left (e.g. `<Icon name="search" size={16} />`).

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="you@example.dev" />
  <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>

<lyra:input> Generated from lyra-ds/blade v0.10.0.

PropDefaultRequiredExample values
labelnull——
hintnull——
errornull—Invalid
size'md'—lg sm
blade
<lyra:input
    name="email"
    type="email"
    label="Email address"
    placeholder="you@example.com"
    autocomplete="email"
/>