- Collect a single-line value.
- Choose the native input type for the value being collected.
- Place one Input inside each Field.
Input
A controlled text input, paired with Field for a persistent label and useful validation.
Implementation previewSee the decisions in action
Try a labelled input, enter a value, and explore the validation state. Field supplies the accessible relationships.
Every example. In one place.
Explore every named example, including states, compositions, and theme variants.
Example source
packages/design-system/src/components/primitives/Input/Input.stories.tsxExport PlaygroundImplementation preview Local Storybook build 0.2.0-preview.1. Source specification status does not approve this runtime.
Stories + source JSON ↗Choose the right responsibility
Input owns the control. Field owns the label and supporting message. Compose them instead of recreating the relationship.
- Using placeholder text as the only label.
- Rendering a controlled input without onChange unless readOnly or disabled.
- Showing a red ring without explanatory text.
A persistent label remains visible after typing. Pair Input with Field whenever the person needs context or corrective guidance.
Explore FieldSmall details carry the experience
Anatomy, feedback, and accessibility are part of the component contract.
ControlOwns the pill surface, selected size, invalid ring, and optional slots.
FieldProvides native single-line input, keyboard, validation, and form semantics.
Leading slotHolds a non-expanding icon or prefix before the field.
Trailing actionHolds a compact interactive action such as clear or show password.
Make the behavior available to everyone.
- Field connects the visible label and helper or error text to the input.
- Use autoComplete and inputMode when applicable.
- Keyboard focus surrounds the complete control.
Keep the important relationships.
- value is required; onChange receives the edited string.
- Use surface=raised directly on a page canvas.
- The return key advances within a form or data-cds-form-scope unless callback behavior is selected.
This interactive implementation is for the web. Imported native specifications do not establish native implementation or parity.
Full component specification preview · 2.0.0
This versioned design-owned specification describes the implementation preview. It remains pending design and engineering sign-off.
{
"$schema": "../../../specs/component-spec.schema.json",
"identity": {
"name": "Input",
"status": "preview",
"version": "2.0.0",
"summary": "A controlled single-line text field with native keyboard types, compact and standard sizes, slots, invalid state, and mobile return-key behavior. It renders no label or message of its own."
},
"parts": [
{
"id": "wrapper",
"label": "Wrapper",
"description": "Carries the caller's class and style around the control."
},
{
"id": "control",
"label": "Control",
"description": "Owns the pill surface, selected size, invalid ring, and optional slots."
},
{
"id": "field",
"label": "Field",
"description": "Provides native single-line input, keyboard, validation, and form semantics."
},
{
"id": "leading",
"label": "Leading slot",
"description": "Holds a non-expanding icon or prefix before the field."
},
{
"id": "trailing",
"label": "Trailing slot",
"description": "Holds a non-expanding suffix after the field."
},
{
"id": "trailing-action",
"label": "Trailing action",
"description": "Holds a compact interactive action such as clear or show password."
}
],
"allowedDesignChoices": {
"variants": {
"base": {
"label": "Base",
"description": "The field has one pill-shaped control treatment."
}
},
"sizes": {
"sm": {
"label": "Small"
},
"md": {
"label": "Medium"
}
},
"types": {
"text": {
"label": "Text",
"description": "General single-line content with no more specific native input type."
},
"password": {
"label": "Password",
"description": "Masks a secret value and requests password input behavior."
},
"email": {
"label": "Email",
"description": "Requests an email keyboard and native email validation."
},
"tel": {
"label": "Telephone",
"description": "Requests a telephone keyboard for phone values."
},
"url": {
"label": "URL",
"description": "Requests a URL keyboard and native URL validation."
},
"search": {
"label": "Search",
"description": "Provides native search semantics for a bare search field."
},
"number": {
"label": "Number",
"description": "Supports native numeric minimum, maximum, and step constraints."
},
"date": {
"label": "Date",
"description": "Requests the native date picker; the value is an ISO YYYY-MM-DD string and the placeholder is platform-owned."
}
},
"surfaces": {
"default": {
"label": "Default",
"description": "Uses the input-container role on a raised host surface."
},
"raised": {
"label": "Raised",
"description": "Uses the raised surface role when the field sits directly on the page canvas."
}
}
},
"variants": [
{
"id": "base",
"label": "Base",
"description": "One pill-shaped field treatment configured through the separate type, surface, and size axes.",
"platforms": [
"ios",
"android",
"web"
]
}
],
"sizes": [
{
"id": "sm",
"label": "Small",
"description": "40-unit compact field for dense contexts."
},
{
"id": "md",
"label": "Medium",
"description": "56-unit standard form field."
}
],
"measurements": [
{
"id": "small-height",
"label": "Small control height",
"kind": "exact",
"token": "--cds-size-40",
"value": 40,
"unit": "px",
"appliesTo": [
"control",
"sm"
]
},
{
"id": "medium-height",
"label": "Medium control height",
"kind": "exact",
"token": "--cds-size-56",
"value": 56,
"unit": "px",
"appliesTo": [
"control",
"md"
]
},
{
"id": "slot-gap",
"label": "Slot gap",
"kind": "exact",
"token": "--cds-space-8",
"value": 8,
"unit": "px",
"appliesTo": [
"leading",
"field",
"trailing",
"trailing-action"
]
}
],
"layout": {
"alignment": "Field text and slots align on the control center line.",
"flow": "Leading slot, flexible field, trailing slot, and trailing action form one row.",
"notes": [
"Wrap Input in Field for a visible label, helper text, or any validation copy; Field is the only owner of error messages.",
"The control fills its parent width."
]
},
"typographyAndColor": {
"typography": [
{
"label": "Medium field text",
"description": "Standard fields use the body ramp.",
"token": "--cds-type-body-size"
},
{
"label": "Small field text",
"description": "Compact fields use the body-small ramp outside the web anti-zoom floor.",
"token": "--cds-type-body-small-size"
}
],
"colors": [
{
"label": "Default container",
"description": "Uses the theme-aware input surface.",
"token": "--cds-input-container"
},
{
"label": "Raised container",
"description": "Uses the raised surface role on a page canvas.",
"token": "--cds-bg-surface"
},
{
"label": "Field text",
"description": "Uses primary text emphasis.",
"token": "--cds-text-primary"
},
{
"label": "Placeholder and slots",
"description": "Use secondary text emphasis.",
"token": "--cds-text-secondary"
},
{
"label": "Invalid",
"description": "Use the readable semantic danger role for error indication in both themes.",
"token": "--cds-text-danger"
}
]
},
"states": [
{
"id": "empty",
"label": "Empty",
"description": "Shows the explicit or type-specific placeholder."
},
{
"id": "focused",
"label": "Focused",
"description": "Accepts input and shows a caret; there is no focus ring, since the design system targets a touch surface and the keyboard/caret already signal focus."
},
{
"id": "filled",
"label": "Filled",
"description": "Shows the controlled value in primary text."
},
{
"id": "invalid",
"label": "Invalid",
"description": "Shows the danger ring and invalid semantics; the control renders no message of its own. An enclosing Field supplies the corrective copy, and a standalone caller renders it elsewhere, such as a form-level summary."
},
{
"id": "disabled",
"label": "Disabled",
"description": "Blocks editing and dims the whole control."
},
{
"id": "read-only",
"label": "Read only",
"description": "Preserves focus and form semantics while preventing edits."
}
],
"behavior": [
{
"label": "Controlled editing",
"description": "Request the next string on every edit while the parent owns the rendered value."
},
{
"label": "Return-key behavior",
"description": "Support advance to the next compatible field or invoke a callback; search and explicit callbacks default to callback behavior."
},
{
"label": "Return-key labels",
"description": "Support enter, done, go, next, previous, search, and send keyboard hints."
},
{
"label": "Native types",
"description": "Preserve text, password, email, telephone, URL, search, number, and date input semantics."
}
],
"accessibility": [
{
"label": "Accessible name",
"description": "Associate a visible Field label or provide an accessible label when the input stands alone."
},
{
"label": "Error relationship",
"description": "Report invalid state on the control itself and render no message. An enclosing Field associates its rendered message with the control; a standalone caller associates the copy it renders elsewhere."
},
{
"label": "Trailing actions",
"description": "Give every interactive trailing action its own accessible name and stable test identifier."
}
],
"contentAdaptation": [
{
"label": "Placeholders",
"description": "Use placeholders as examples or hints, never as the only persistent visible label for complex forms."
},
{
"label": "Long values",
"description": "Let the native single-line field scroll horizontally; use Textarea for multiline content."
}
],
"motionHaptics": {
"motion": [
{
"label": "Focus and validation",
"description": "Change borders and rings without moving the control."
}
],
"haptics": [
{
"label": "No intrinsic feedback",
"description": "Typing and focus do not request design-system haptics; a trailing action owns its own feedback."
}
]
},
"platformDifferences": [
{
"platforms": [
"web"
],
"description": "Small field text is floored at the 16px body size in the webview instead of rendering the 14px body-small size.",
"rationale": "WKWebView zooms focused inputs below 16px; the font floor prevents an unexpected viewport jump while retaining the compact 40px shell."
}
]
}Carry the decisions into code
The same component contract supports a person reading the page and an agent implementing it.
Build a Input component using the Cloaked design system. Read https://design.cloaked.team/data/components/input.json first. Use the documented component API and semantic tokens. Preserve keyboard access, clear labels, and validation behavior. Treat this implementation as a review preview; report any missing requirements.