Input
Text-like native inputs: text, email, search, tel, url, and similar. Labels and messages belong to Field. For several lines, use TextArea; for passwords, Password input.
Installation
bun add @harmo-ui/css @harmo-ui/reactnpm install @harmo-ui/css @harmo-ui/reactpnpm add @harmo-ui/css @harmo-ui/reactyarn add @harmo-ui/css @harmo-ui/reactbunx harmo-ui add inputnpx harmo-ui add inputpnpm dlx harmo-ui add inputyarn dlx harmo-ui add inputUsage
import { Field, Input } from "@harmo-ui/react";
<Field label="Billing email" error="Enter a valid email address.">
<Input name="billing-email" type="email" autoComplete="email" />
</Field>Examples
Default
34px tall and as wide as its container. The placeholder is gray; give the input a label in a Field rather than relying on it.
<div class="hfield">
<label class="hlabel" for="company">Company</label>
<input class="hinput" id="company" name="company" type="text" autocomplete="organization" placeholder="Acme Inc." />
</div>
<div class="hfield">
<label class="hlabel" for="full-name">Full name</label>
<input class="hinput" id="full-name" name="full-name" type="text" autocomplete="name" value="Jane Smith" />
</div>Types
Any text-like type works, and the browser brings its keyboard and autofill. Give each an autocomplete value where one fits.
Invalid
aria-invalid="true" turns the border red, with a red ring when focused. Set it only after the app has validated the value.
Enter a valid email address.
<Field label="Billing email" error="Enter a valid email address.">
<Input
name="billing-email"
type="email"
autoComplete="email"
defaultValue="not-an-email"
/>
</Field>Read-only and disabled
Both get a gray background. A readonly input can still be focused and copied from; a disabled one can't, and its text fades.
Next to a button
In a flex row, the input takes the room the button leaves. The row here is a plain flex container of your own.
<div style={{ display: "flex", gap: 8 }}>
<Input
type="search"
aria-label="Search conversations"
placeholder="Search conversations"
/>
<Button variant="secondary">Search</Button>
</div><div style="display: flex; gap: 8px">
<input class="hinput" type="search" aria-label="Search conversations" placeholder="Search conversations" />
<button class="hbutton" data-variant="secondary" type="button">
<span class="hbutton-label">Search</span>
</button>
</div>API reference
React
<Input> renders the <input>. In a Field, it takes the field's id and descriptions. Its props are the input's attributes.
HTML
An <input class="hinput" type="…"> with a text-like type, named by a <label for> matching its id, or by aria-label. Load input.css; field.css for a label and messages. It needs no script.
| Hook | Effect |
|---|---|
placeholder | Shown in --harmo-color-text-tertiary |
aria-invalid="true" | --harmo-color-danger border, and a red ring when focused |
readonly | Secondary background; still focusable and copyable |
disabled | Secondary background, no shadow, and --harmo-color-text-tertiary text |
See Input's full contract.
Accessibility
- Name it with a
<label for>in a Field, and connect a description and error witharia-describedby. - Set
aria-invalid="true"only after the application has validated the value, and give fields anautocompletevalue where one fits. - The default border is 1.23:1 on white, a deliberately light look below WCAG 1.4.11's 3:1 for a field's edge; the faint shadow doesn't make up the difference. For 3.42:1, set
--harmo-input-color-border: var(--harmo-color-border-control)on:root. Selects and textareas follow, since they share the token.