Input
canonSingle-line input in text, email, url, code, number and short widths.
States include read-only (canon since 28 Sep 2026, !4102): --surface-75, full --fg text, cursor: text, focus ring kept; replaces the scoped .finput[readonly]. Registered exceptions from <Input> (AD 28 Sep 2026, !4110) — inline editing in context, a 32px box would break the header or the tool: .nt-bub-url (link field inside the note formatting bubble) and .sgb-th-edit (column rename in the segment table header), both --control-h-sm (24px); .sgb-th-edit carries the focus ring like .rr-edit; on touch (pointer: coarse) .nt-bub-url is 44px. Any other bare <input> with a text-field box class fails the input-raw HARD rule.
Used in 90 files · 37 areas · 271× — components/accounting, components/assistant, components/callwrapup, components/clen-tymu, components/datamart, components/mail …
@acrm/ui <Input>.acrm-input .acrm-input--num .acrm-input--code .acrm-input--short +3SourceStoryLegacy card Inputs.htmlDefault
export const Default = () => {
const [v, setV] = useState('');
return (
<div style={{ width: 360 }}>
<Input value={v} onChange={(e) => setV(e.target.value)} placeholder="Company name" />
</div>
);
};Variants
export const Variants = () => (
<div style={row}>
<Labeled label="type=text">
<Input type="text" className="acrm-input--short" placeholder="Jane Doe" />
</Labeled>
<Labeled label="type=email">
<Input type="email" className="acrm-input--email" placeholder="[email protected]" />
</Labeled>
<Labeled label="type=url">
<Input type="url" className="acrm-input--email" placeholder="https://company.com" />
</Labeled>
<Labeled label="type=number">
<Input type="number" className="acrm-input--num" placeholder="0" />
</Labeled>
</div>
);Sizes
export const Sizes = () => (
<div style={grid}>
<Labeled label="--num (88px)">
<Input className="acrm-input--num" defaultValue="12" />
</Labeled>
<Labeled label="--code (132px)">
<Input className="acrm-input--code" defaultValue="CZ12345678" />
</Labeled>
<Labeled label="--short (210px)">
<Input className="acrm-input--short" defaultValue="Jane Doe" />
</Labeled>
<Labeled label="--email (280px)">
<Input className="acrm-input--email" defaultValue="[email protected]" />
</Labeled>
<div style={{ width: 480 }}>
<Labeled label="default (100% of the container)">
<Input defaultValue="Full width of the field column" />
</Labeled>
</div>
</div>
);States
export const States = () => (
<div style={grid}>
<div style={row}>
<Labeled label="placeholder">
<Input className="acrm-input--short" placeholder="Enter a value" />
</Labeled>
<Labeled label="filled">
<Input className="acrm-input--short" defaultValue="Acme Robotics" />
</Labeled>
<Labeled label="read-only">
<Input className="acrm-input--short" defaultValue="[email protected]" readOnly />
</Labeled>
<Labeled label="disabled">
<Input className="acrm-input--short" defaultValue="Disabled" disabled />
</Labeled>
<Labeled label="error (.is-error)">
<Input className="acrm-input--short is-error" defaultValue="123" aria-invalid />
</Labeled>
</div>
<span style={{ color: 'var(--fg-muted)', font: 'var(--small)' }}>
Focus: border turns --accent with a 3px translucent ring (16 %); error uses the same ring on
--critical.
</span>
</div>
);Composition
export const Composition = () => {
const [from, setFrom] = useState('10');
const [to, setTo] = useState('50');
return (
<div style={grid}>
<Labeled label="range from–to (.acrm-range)">
<div className="acrm-range">
<Input value={from} onChange={(e) => setFrom(e.target.value)} aria-label="From" />
<span className="acrm-range-dash">–</span>
<Input value={to} onChange={(e) => setTo(e.target.value)} aria-label="To" />
</div>
</Labeled>
</div>
);
};