ADR-094 ActifActive contract

Min/max-width for single-line controls, and a reserved ceiling for a future textarea

DateDate
2026-09-09
DécideursDecision makers
Guilherme Negreiros — Design System Lead

Context

Building mockups in the Figma sandbox file surfaced a real question: agtc-input's .control had no min-width/max-width at all, so its rendered width was purely whatever its container imposed — from 240px (the Figma master's stale fixed field, see the same session's Input field FILL fix) up to 720px in one mockup card. Nothing in the token system or the component itself expressed an intentional floor or ceiling, which is a real gap: any container width becomes a "valid" input width, including implausible ones (a field stretched to 720px reads as a mistake, not a design choice).

Decision

Add three new semantic tokens under semantic.size.control:

TokenValuePrimitiveApplies to
size.control.min-width64px{primitive.space.16}agtc-input .control — floor only
size.control.max-width480px{primitive.space.120}agtc-input .control — ceiling only
size.control.max-width-multiline640px{primitive.space.160}Reserved for a future agtc-textarea — not consumed by any component today

components/agtc-input.js's .control rule now sets both:

.control {
  min-width: var(--agtc-semantic-size-control-min-width);
  max-width: var(--agtc-semantic-size-control-max-width);
}

Research behind the values

Nielsen Norman Group: mismatched field sizes cause measurable user hesitation; a short-answer field (e.g. phone number) stretched to fill its container is a missed signal, not a neutral choice.

size a text input around min-inline-size: 7ch (~64px at body size) specifically to stop it collapsing to an unreadable sliver in a tight flex/grid parent. It is not meant to represent "full width on a small mobile viewport" — that width already comes for free from FILL/percentage sizing; deriving a floor from a viewport calculation (360 − 32 = 328px, the alternative considered and rejected below) would instead prevent the same Input from ever being used in any narrower legitimate context (a compact search box, a table-cell filter, an inline field).

explicitly declines to set one, only warning against "excessively wide fields disproportionate to the intended data"), but production design systems converge in practice around a few hundred px for a generic single-line field; 480px also happens to match this session's own 400px-wide login card comfortably.

hard ceiling of 80 characters per line; typography research (Baymard, UXPin) converges on a 45–75 character sweet spot for readability. 640px is a px approximation of ~70 characters at typography.body (16px) for contexts that need a fixed value (Figma, or a platform without ch support) — actual code should prefer max-width: 70ch directly where available, since it stays correct across font-size and zoom changes in a way a fixed px value cannot.

Rejected alternatives

AlternativeReason for rejection
min-width = 328px (360px mobile viewport − 32px page padding)Conflates "the width Input happens to reach via FILL on a small screen" with "the narrowest legitimate use of Input" — would make the component unusable in any container narrower than 328px (compact search, table-cell filter, inline field), for no accessibility or usability gain.
No min/max at all (Carbon's stance)Carbon's own reasoning is "avoid excessive width," which is exactly the failure mode observed (720px in a mockup) — leaving it unenforced already produced a visible defect once, in this same session.
Build agtc-textarea now to consume the multiline ceilingOut of scope for a width-token decision; no UX pattern review (ux-patterns-sources.md) has been run for a new component. The token is reserved and documented so the decision doesn't need to be re-researched later.

Consequences

documented in guidelines/components/input.md.

maxWidth frame constraints on its field sub-frame, mirroring the code change, so the contract holds in both surfaces (tracked as part of this same session's work).

agtc-textarea build should consume it (or supersede it with ch-based sizing in code) rather than re-deriving the research from scratch; a UX pattern review is still required before that component ships (ux-patterns-sources.md).

tokens-system.md. Two new primitive values were added (primitive.space.120 = 480px, primitive.space.160 = 640px), continuing the existing 4px-multiple naming convention (primitive.space.16 = 4×16 = 64px, etc.) — same governance tier, same approval.

← ADR-093