Input
A single-line text input. Inside a Field it picks up its id, description, error and required state automatically.
<Input aria-label="Email" type="email" placeholder="you@company.com" />Import
import { Input } from "@merid/react";Examples
Sizes
sm 36px, md 46px (default), lg 50px.
<Input size="sm" placeholder="Small, 36px" />
<Input size="md" placeholder="Medium, 46px" />
<Input size="lg" placeholder="Large, 50px" />Leading and trailing
leading and trailing add decorative icons, prefixes or units inside the frame. They are aria-hidden, so put anything meaningful (like a currency) in the label too. When either is set, the input is wrapped in .mrd-input-group and className moves to the wrapper.
<Input aria-label="Search" leading={<SearchIcon />} placeholder="Search projects" />
<Input aria-label="Amount" type="number" trailing="TRY" defaultValue="250" />Invalid, disabled, read-only
invalid forces the invalid style and aria-invalid; inside a Field it follows the Field's error. disabled and readOnly are the native attributes.
<Input aria-label="Invalid" invalid defaultValue="not-an-email" />
<Input aria-label="Disabled" disabled defaultValue="Disabled" />
<Input aria-label="Read only" readOnly defaultValue="Read only" />Controlled
Input is a plain <input>: use value + onChange to control it, or defaultValue to leave it uncontrolled.
meridui.dev/…
const [value, setValue] = useState("");
<Input
aria-label="Workspace URL"
value={value}
onChange={(event) => setValue(event.target.value)}
placeholder="acme"
/>
<Text size="xs" tone="muted">meridui.dev/{value || "…"}</Text>API reference
Input forwards its ref to the <input> and passes every other native input attribute through. className and style always go on the root element: the <input> itself, or the .mrd-input-group wrapper when leading or trailing is set. type defaults to "text".
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "md" | "lg" | "md" | Height: sm 36px, md 46px, lg 50px. |
invalid | boolean | – | Forces the invalid style (`data-invalid`) and `aria-invalid`. Inside a Field, derived from its error. |
leading | ReactNode | – | Decorative element before the text (icon, prefix). |
trailing | ReactNode | – | Decorative element after the text (icon, unit). |
type | string | "text" | Native input type. |
Styling
| Hook | Values |
|---|---|
.mrd-input | The <input> |
.mrd-input-group | Wrapper, only when leading or trailing is set |
.mrd-input-group__addon | Addon slot, with data-side leading · trailing |
data-size | sm · md · lg (on input and group) |
data-invalid | Present when invalid; drives the danger border (aria-invalid carries the semantics) |
Component variable: --mrd-input-height, set per size.
.filters .mrd-input {
--mrd-input-height: 40px;
}Accessibility
- Every input needs a name: a visible Label / Field, or
aria-labelwhen the purpose is obvious from context (like search). - Placeholder text is not a label; it disappears when typing and has low contrast.
| Key | Action |
|---|---|
| Tab | Moves focus to the input. |
Guidelines
Do
Match the input size to neighbouring buttons so a row shares one height.
Avoid
Put interactive elements like buttons in leading or trailing — addons are hidden from assistive tech.
Related
- Field — label, description and error wiring.
- Textarea — multi-line text.
- NativeSelect — pick from a list.