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.
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
Specificații
| Ce | md (implicit) | lg |
|---|---|---|
| înălțime · radius | 40 · --r-lg (20) | 44 · --r-lg (20) |
| padding orizontal = radius | 16 | 20 |
| text | Inter 14/20 · 400 · ink | Inter 16 · 400 · ink |
| bordură | 1px --c-input-border (ink @ 30%) · hover --c-input-border-hover | |
| focus | border --c-fog + halo 0 0 0 3px rgba(122,117,112,.14) — neutru, niciodată brand | |
| eroare · succes | border --c-error + fundal --c-error-bg · border --c-success; mesajul e al câmpului (.field-help) | |
| disabled | fundal --c-bej-1 · text --c-mist | |
| placeholder | --c-mist · exemplu de format („RO12345678”), nu instrucțiune | |
padding = radius — textul începe unde se termină curba
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.
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ă.
Î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.
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
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ă.
Ce intră în addon
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.
.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.
.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ă.
În modal · mărimea lg
Modal-ul e un context dedicat unei singure acțiuni, deci folosește exclusiv lg (44h / 16px) — input și buton la aceeași înălțime. Restul e pe Modal.