MiHCM
primitives/@mihcm/ui·v0.21.0·stable

Input

Single-line text entry. Default + destructive variants, three sizes, optional leading/trailing icons. WCAG 2.1 AA out of the box (aria-invalid, aria-required, focus ring).

Use cases

  • Single-line text entry — email, search, URL, username.
  • Form fields that need explicit invalid styling tied to ARIA.
  • Inputs with a leading or trailing affordance: search glyph, clear button, validation checkmark.

When NOT to use

  • Multi-line input — use a Textarea primitive (planned).
  • A toggle — use Switch or Toggle (planned).
  • Date / time pickers, comboboxes — separate primitives where the text field is one part of a larger widget.

Anatomy

The component is a styled wrapper around the platform input. The wrapper owns the border, padding, and focus ring; the input is transparent and inherits the wrapper's text color so leading/trailing icons compose cleanly.

┌──────────────────────────────────────────────┐
│ [leadingIcon]  input element  [trailingIcon] │
└──────────────────────────────────────────────┘

Use the wrapper's className for layout (max-width, full-width) and inputClassName for the input itself (font, letter-spacing). Most consumers never need inputClassName.

Variants

VariantUse when
defaultStandard text entry.
destructiveThe field has a validation error. Use invalid instead of toggling the variant by hand — it drives the visual and the ARIA state in one prop.

Sizes

SizeHeightUse when
sm36 pxDense forms, table-cell editors, secondary fields.
md40 pxDefault for most desktop forms.
lg48 pxPrimary mobile fields and high-emphasis form rows.

Validation pattern

Pair the input with a label and an error message element. Wire them with htmlFor and aria-describedby — Input deliberately doesn't render the label or the message itself so consumers can put them wherever the layout calls for.

<label htmlFor="email" className="text-sm font-medium">
  Email <span className="text-destructive">*</span>
</label>
<Input
  id="email"
  type="email"
  required
  invalid={!!error}
  aria-describedby={error ? 'email-error' : undefined}
/>
{error && (
  <p id="email-error" className="mt-1 text-sm text-destructive">
    {error}
  </p>
)}

Composition

  • Pair leadingIcon with a lucide-react glyph (e.g. <Mail />) for affordance.
  • Use trailingIcon for a clear button or a validation checkmark.
  • For password fields, set type="password". Show/hide affordances are a consumer concern — Input keeps its surface small on purpose.
  • Button — pair as the form submit.
  • Text — labels and helper text.
  • Planned: Textarea, Combobox, Search.