Input

.input e controlul — cutia în care scrii. Nu știe de etichetă, ajutor sau eroare: alea sunt ale câmpului, pe Field. Ce e în interiorul bordurii — iconiță, text, buton, sau eticheta însăși — e Input group.

Trei nume, o singură graniță — bordura controlului.
Input · .input e controlul: cutia în care scrii. Nu știe de etichetă, ajutor sau eroare.
Field · .field e tot ce e în afara bordurii: etichetă, ajutor, eroare, orientare. Agnostic la control.
Input group · .input-group e tot ce e în interiorul bordurii: iconiță, text, buton, scurtătură — sau eticheta însăși. Nu e o pagină, e același control cu ceva în el.
Se cuibăresc, nu concurează: .field > .input-group > .input. Împărțirea e a lui shadcn — Input e controlul, Field „combines labels, controls, and help text”, InputGroup „adds addons, buttons, and helper content to inputs”.

Markup canonic · components/input.json

sursa = JSON · generat de scripts/build-catalog.py

Specificații

Cemd (implicit)lg
înălțime · radius40 · --r-lg (20)44 · --r-lg (20)
padding orizontal = radius1620
textInter 14/20 · 400 · inkInter 16 · 400 · ink
bordură1px --c-input-border (ink @ 30%) · hover --c-input-border-hover
focusborder --c-fog + halo 0 0 0 3px rgba(122,117,112,.14) — neutru, niciodată brand
eroare · succesborder --c-error + fundal --c-error-bg · border --c-success; mesajul e al câmpului (.field-help)
disabledfundal --c-bej-1 · text --c-mist
placeholder--c-mist · exemplu de format („RO12345678”), nu instrucțiune

padding = radius — textul începe unde se termină curba

16
text
16

Eticheta și ajutorul au același padding-left: 16px, ca textul din label, din input și din help să pornească din aceeași coloană. Distanțele în afara controlului (4 în câmp, 18 între câmpuri) sunt pe Field · Spațiere.

Suprafața · regula de context

Inputul nu-și alege fundalul singur — îl dă cardul de sub el. Alb pe bej-1, tonal pe alb, alb pe canvas bej-0. Motivul e măsurabil: conturul de 30% dă 2.00:1 peste alb (sub 3:1, WCAG 1.4.11), deci pe card alb inputul trece pe .tonal, cu contur la 46% (3.16:1). Tonalul nu stă niciodată pe bej-1 — acolo cade la 2.78:1.

A · alb pe card bej-1 — implicit (Dublin, dashboard, modal)
Apare pe facturile emise.
B · tonal pe card alb — .input.tonal (setup, wizard)
Apare pe contractul de servicii.
C · pe canvas bej-0 cu dot grid (flow) — alb, fără fundal sau bordură în plus · câmpurile sunt live
Validat în Registrul Comerțului.
Format email invalid.

Eticheta în interiorul bordurii

Un input group cu eticheta ca bară block-start — forma din shadcn. Eticheta e pink în repaus, pink-deep pe focus; bordura rămâne neutră. Doar client-facing (Dublin, landing) — formularele interne folosesc .field neutru. Se recunoaște prin conținut, .block-start > .field-label, nu printr-o clasă nouă.

repaus · label pink
focus · label pink-deep, halo neutru
eroare · label iese din brand, devine ink
textarea · scroll intern, resize vertical, label rămâne deasupra

În eroare, eticheta nu devine roșie și nu rămâne pink: brandul nu poartă sens negativ, iar pink lângă roșu pe tint roșu măsoară 3.33:1. Devine ink (17.48:1).

Textarea

E .input pe un <textarea>, nu o clasă separată. Fără regula dedicată ar moșteni height: 40px și s-ar strânge la un rând.

label deasupra · .field
label în interior · .input-group + block-start
textarea.input          height auto · min-height 88px (~4 rânduri) · padding 10 16
                        resize vertical · scroll intern
cu etichetă în bordură  min-height 60px (~3 rânduri) · padding 2 16 7 · resize vertical
.input-group >          resize none — marginea ar trece peste toolbar (vezi mai jos)

Input group · addon-uri în interiorul bordurii

Iconiță, text static, buton, spinner, scurtătură — lipite de control, în aceeași bordură. Regula: bordura trece pe carcasă, controlul o pierde. Echivalentul lui InputGroup din shadcn; la noi e o secțiune a inputului, nu o pagină — e același control, cu ceva în el.

Granița e cea din capul paginii: eticheta, ajutorul și eroarea sunt ale câmpului; ce e aici e în bordură. Căutarea din topbar n-are etichetă, deci e .input-group singur.

.input-group                    carcasa · h 40 · padding 0 16 · gap 8 · r --r-lg
├── .input  sau  textarea.input   controlul, copil direct — fără bordură, fundal, înălțime
├── .input-group-addon            slotul · 14px fog · svg 16 · implicit inline-start
│   ├── .input-group-text         text static (RON · https:// · 0/280) · .ink pentru unități
│   ├── .kbd                      scurtătură
│   └── .btn.xs / .btn.sm         buton PLAT: .ghost · .outline · .outline-pink
└── .input-group-addon.inline-end al doilea slot

în carcasă — padding 16, gap 8 între addon și control

16
svg
8
.input
8
kbd
16

Aliniere

Pe input: inline-start (implicit) și inline-end. block-start și block-end — o bară pe rând propriu; carcasa devine coloană: toolbar pe textarea, sau eticheta în bordură când bara ține un .field-label. Addon-ul se scrie după control în DOM: poziția o face order, ordinea de tab rămâne cea corectă.

inline-start · inline-end
RON
block-start · block-end pe textarea — bare pe rând propriu, .ruled pune linia
mentiuni-factura.md 0/280

Ce intră în addon

iconiță · text prefix și sufix · kbd
⌘K
https:// .ro
buton plat · .btn.ghost.xs.icon-only · .btn.outline.xs
@

Butonul din addon e o acțiune a câmpului, nu CTA-ul ecranului — de asta e plat și nu se ridică la hover; grupul anulează ridicarea chiar și pe o variantă plină pusă din greșeală. Stările (hover, focus, eroare, disabled) sunt pe carcasă, cu valorile inputului.

sumă cu monedă, la mărime normală · buton în addon + .popover.align-end — varianta „5+ câmpuri” a lui Money input
Migrare v8: .input-group însemna până acum un rând de câmpuri — ăla e .field-row. .field.input-em a dispărut: eticheta din bordură e .input-group cu un addon block-start care ține .field-label, iar eticheta trece după input în DOM (ordinea de tab). .search-wrap e deprecat: iconița lui era position: absolute și nu rezerva spațiu. Rămâne în CSS doar cât îl folosește referința Dublin (oglinda producției); dispare odată cu sync-ul în BFF. Focusul la click pe addon e un handler în aplicație (carcasa e <div>, ca la shadcn, fiindcă addon-ul poate conține butoane).

OTP

Celula e un .input obișnuit — .otp schimbă mărimea și forma, nimic altceva. Suprafața urmează regula de context de mai sus: alb pe bej-1, tonal pe alb.

pe card bej-1 → celule albe
pe card alb → celule tonale
.otp .input      48 × 56 · cifra 20px/500 tabular · radius --r-md (nu pastilă)
                 = .input.lg + 1 treaptă pe X (44→48), 3 pe Y (44→56)
                 lățimea e plătită de rând (6 celule pe un telefon), înălțimea nu
.otp             gap 8 · .otp-sep opțional la mijloc · mobil: gap 6, mărimi neschimbate

Un input per cifră, fiecare cu aria-label — nu un input cu letter-spacing, care rupe paste-ul și cititorul de ecran. Eroarea e mesaj sub câmp, nu contur roșu pe fiecare celulă.