Component reference
Input
A single-line text input.
Preview
Control centers and symmetry
Checks the vertical center and top/bottom symmetry of single-line inputs, selects, button icons/text, and the inline composer on one screen; shared by visual review and geometry regressions.
render() {
const choice = signal("current");
const rowChoice = signal("current");
const view = signal("list");
return (
<div className="workshop-stack" data-basic-quality-scene>
<Specimen label="Single-line inputs and selects" align="start">
<Input aria-label="Project name" value="Workspace" data-batch1="input" />
<Input
aria-label="Project name placeholder"
placeholder="Project name"
data-batch1="input-placeholder"
/>
<Select aria-label="Current workspace" value="current" data-batch1="select">
<option value="current">Current workspace</option>
<option value="new">New workspace</option>
</Select>
<ChoiceSelect
id="basic-quality-choice"
aria-label="Select model"
value={choice}
onValueChange={(value) => {
choice.value = value;
}}
data-batch1="choice-select"
options={[
{ value: "current", label: "DeepSeek-V4-Pro" },
{ value: "fast", label: "DeepSeek-V4-Fast" },
]}
/>
</Specimen>
<Specimen label="One row of every single-line control" align="start">
{/* Top-aligned on purpose: the row only lines up if every height agrees. */}
<Inline gap="compact" align="start" data-mixed-row>
<Input aria-label="Filter name" placeholder="Name" />
<SearchInput label="Search files" placeholder="Search" />
<Select aria-label="Status">
<option>Any status</option>
</Select>
<ChoiceSelect
id="basic-quality-row-choice"
aria-label="Owner"
value={rowChoice}
onValueChange={(value) => {
rowChoice.value = value;
}}
options={[
{ value: "current", label: "Anyone" },
{ value: "me", label: "Me" },
]}
/>
<NumberInput defaultValue={10} aria-label="Limit" />
<SegmentedControl
id="basic-quality-row-view"
label="View"
value={view}
onValueChange={(value) => {
view.value = value;
}}
options={[
{ value: "list", label: "List" },
{ value: "grid", label: "Grid" },
]}
/>
<Button variant="outline">Reset</Button>
<Button>Apply</Button>
<IconButton label="Refresh">
<Icon name="refresh-cw" />
</IconButton>
</Inline>
</Specimen>
<Specimen label="Actions" align="start">
<div className="workshop-row">
<Button data-batch1="button-text">Save changes</Button>
<Button data-batch1="button-icon-text">
<Icon name="search" />
Search
</Button>
<IconButton label="Search" data-batch1="icon-button">
<Icon name="search" />
</IconButton>
</div>
</Specimen>
<Specimen label="Switches and checkboxes" align="start">
<div className="workshop-row">
<Checkbox label="Keep draft" defaultChecked data-batch1="checkbox" />
<Switch label="Notify when complete" data-batch1="switch" />
</div>
</Specimen>
<Specimen label="Inline input" align="start">
<div style={{ width: "100%" }}>
<ChatComposer
layout="inline"
placeholder="Write a message…"
inputLabel="Message"
submitLabel="Send"
onSubmit={(event) => event.preventDefault()}
data-batch1="composer"
/>
</div>
</Specimen>
</div>
);
}Installation
Usage
Taken from the examples on this page.
import { Input } from "meowtail";
<Input aria-label="Project name" value="Workspace" />Examples
The other stories that show this component.
Normal and long labels
Native input behavior and Field label association; long labels, helper descriptions, and multi-line content are shown together.
render: () => {
const delivery = signal("review");
return (
<form className="workshop-stack workshop-constrained" data-project-form novalidate>
<Field
label="Project name"
htmlFor="workshop-project"
description="Local demo only; nothing is saved to a service."
>
<Input id="workshop-project" name="project" value="Meowland" required />
</Field>
<Field
label="Delivery method"
htmlFor="workshop-delivery"
description="Review the diff first, then decide whether to submit."
>
<Select
id="workshop-delivery"
name="delivery"
aria-describedby="workshop-delivery-description"
value={delivery}
required
onChange={(event) => {
delivery.value = (event.currentTarget as HTMLSelectElement).value;
}}
>
<option value="draft">Keep draft</option>
<option value="review">Review the diff first</option>
<option value="export">Export results</option>
</Select>
<div className="workshop-foundation-field-action">
<span>Not sure which to pick?</span>
<Button
variant="quiet"
size="small"
onClick={() => {
delivery.value = "review";
}}
>
Use recommended settings
</Button>
</div>
</Field>
<Field
label="Add constraints this work must follow and how you want the results checked when done"
htmlFor="workshop-notes"
>
<Textarea
id="workshop-notes"
rows={4}
placeholder="Write down constraints, or paste longer content…"
/>
</Field>
<div className="workshop-row">
<Button type="submit">Save project</Button>
<Button type="reset" variant="quiet">
Restore initial values
</Button>
</div>
<Note id="project-feedback" role="status">
Change the name and save; leave it empty to see validation feedback.
</Note>
</form>
);
}Error and disabled
The error description is associated with the control by a real Field; a disabled input stays readable. This sample uses a fixed error state.
render: () => (
<div className="workshop-stack workshop-constrained">
<Field
label="Project name"
htmlFor="workshop-invalid"
error="Enter a project name; spaces alone are not enough."
>
<Input id="workshop-invalid" value="" />
</Field>
<Field
label="Working directory"
htmlFor="workshop-disabled"
description="The directory cannot be changed while running."
>
<Input id="workshop-disabled" value="/workspace/meowland" disabled />
</Field>
<Field
label="Runtime environment"
htmlFor="workshop-disabled-select"
description="Cannot be switched while work is in progress."
>
<Select id="workshop-disabled-select" disabled>
<option>Local workspace</option>
</Select>
</Field>
<Field
label="Additional notes"
htmlFor="workshop-invalid-notes"
error="The description exceeds the length allowed by this sample; shorten it and continue."
>
<Textarea id="workshop-invalid-notes" rows={3}>
A longer description that needs to be added.
</Textarea>
</Field>
</div>
)Read-only, errors and long content
Read-only content can still be selected and copied; disabled content cannot be edited. Explicit errors, composed fields and long content keep a clear association.
render: () => (
<div className="workshop-composition-columns">
<section className="workshop-stack">
<Field
label="Project path (read-only)"
htmlFor="readonly-path"
description="Can be selected and copied; it cannot be changed here."
>
<Input
id="readonly-path"
readonly
value="/workspace/meowland/packages/meowtail/components/long-project-reference"
/>
</Field>
<Field label="Search files" htmlFor="search-files">
<Input id="search-files" type="search" placeholder="Enter a file name…" />
</Field>
<Field
label="Notification email"
htmlFor="invalid-email"
invalid
error="Enter a complete email address."
>
<Input id="invalid-email" type="email" value="meow@" />
</Field>
<Field label="Access passphrase (disabled)" htmlFor="disabled-password">
<Input id="disabled-password" type="password" value="demo-only" disabled />
</Field>
<Field
label="Check range"
description="For composed fields, the caller associates the label and description separately."
descriptionId="range-description"
>
<div className="workshop-foundation-range">
<label>
From{" "}
<Input
aria-label="Start line"
aria-describedby="range-description"
type="number"
value="1"
min="1"
/>
</label>
<label>
To{" "}
<Input
aria-label="End line"
aria-describedby="range-description"
type="number"
value="80"
min="1"
/>
</label>
</div>
</Field>
</section>
<section className="workshop-stack">
<Field label="Delivery notes (editable)" htmlFor="long-notes">
<Textarea id="long-notes" rows={6}>
First, confirm every component stays readable on narrow screens. Second, keep user input
while switching themes. Third, open a dialog with the keyboard, cancel it and return.
Long content should wrap naturally; never drop the evidence for checks to keep the
screen tidy.
</Textarea>
</Field>
<Field label="Last check record (read-only)" htmlFor="readonly-notes">
<Textarea id="readonly-notes" rows={3} readonly>
The record is kept for checking. Read-only does not mean inaccessible.
</Textarea>
</Field>
<Field label="Waiting for the connection to return" htmlFor="disabled-notes">
<Textarea id="disabled-notes" rows={3} disabled>
Continue editing once the connection returns.
</Textarea>
</Field>
</section>
</div>
)API reference
Props
| Prop | Type | Default |
|---|---|---|
type | string | "text" |
Also takes className, children and the attributes and events of its root element.
DOM parts
Registry
The component is registered as input in the meowtail component registry.