Dogfood pe import + Trimiteri (mobil/tableta <1024px), pur CSS + markup, backend
trimitere neatins:
- Card compact real pentru .tabel-trimiteri (preview + Trimiteri): vehicul=titlu,
stare=pill dreapta-sus, operatie+cod, meta data/km muted, nota mica. Inlocuieste
stiva generica eticheta+valoare (carduri de ~450px -> ~135px). Anuleaza regula
desktop tr.trimitere-row > td{padding:11px} in blocul compact.
- FIX editare preview: OOB swap pe <tr> esua tacit in htmx 1.9 (un <tr> brut se
pierde la parsarea unui fragment fara context de tabel) -> randul ramanea cu
starea veche dupa salvare. Inlocuit cu reload complet al preview-ului prin
HX-Trigger:reincarcaPreview + detalii randSalvat. /editeaza si /confirma-review
folosesc helper-ul _raspuns_rand_salvat.
- Feedback post-salvare: toast global "Randul N actualizat · <stare>" + scroll +
flash pe randul actualizat (base.html window.arataToast + listener randSalvat).
- Modal editare: Salveaza + Anuleaza pe acelasi rand (sistem .act): desktop text,
mobil doua iconite Lucide 44px alaturate (save/x). Macro icon('x') + .act-primary.
- Randuri deja-trimise/duplicate colapsate implicit in preview + toggle "Arata N".
- Select "Operatii de mapat" full-width pe mobil (nu mai iese din viewport).
- Bara de filtre Trimiteri adaptata mobil: pills pe banda cu scroll orizontal,
cautare vehicul proeminenta (nu 8 butoane full-width stivuite).
- Nota preview = culoarea camp-fix (accent) ca sa atraga atentia; hint-urile
camp-fix per-camp scoase (campul Note e self-explanatory).
- Confirmare trimitere: scos campul email (Declarant); text mai clar
("Confirma numarul din N gata de trimis"). Backend confirmed_by ramane optional.
Teste: contractul OOB (rupt in browser) inlocuit cu noul contract
(reincarcaPreview + randSalvat) in test_web_preview_edit / test_preview_edit_ui /
test_import_review. Suita: 992 passed (exclus live).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
234 lines
11 KiB
Markdown
234 lines
11 KiB
Markdown
# design.md — Sistemul de design Gateway RAR AUTOPASS
|
||
|
||
Sursa de adevar pentru deciziile vizuale ale aplicatiei web. **Orice plan de design
|
||
(`/plan-design-review`, `/design-consultation`, `/design-review`) si orice modificare
|
||
de UI trebuie sa porneasca de aici.** Unde un mockup sau o propunere difera de acest
|
||
document, documentul are dreptate (sau se actualizeaza explicit, intr-un commit separat).
|
||
|
||
Limba UI: romana, fara diacritice in cod/atribute tehnice, cu diacritice acceptate in
|
||
textul vizibil (fontul are `latin-ext`). Fara emoji.
|
||
|
||
CSS-ul traieste inline in `app/web/templates/base.html` (un singur `<style>`). Nu exista
|
||
build step. Tokenii de mai jos sunt variabile CSS reale definite acolo.
|
||
|
||
---
|
||
|
||
## 1. Principii
|
||
|
||
1. **Compact, nu inghesuit.** Densitate mare de informatie utila, dar cu ritm si spatiu.
|
||
Pe ecrane mici aratam ESENTIALUL, nu tot ce incape pe desktop. Restul intra in detaliu
|
||
(modal) sau in linii secundare mici.
|
||
2. **Compactarea e si pentru desktop.** Cand o componenta e mai lizibila compacta (ex.
|
||
wizard-ul de import), forma compacta se aplica pe toate latimile, nu doar pe mobil.
|
||
3. **Mobile-first ca verificare, nu ca scuza.** Orice ecran trebuie sa fie complet
|
||
utilizabil la 360px latime, fara scroll orizontal de pagina si fara text rupt vertical.
|
||
4. **Starea prin text + culoare, niciodata doar culoare** (accesibilitate; pill-uri cu
|
||
eticheta umana, glife ✓/✗ cu text).
|
||
5. **O singura zona de actiune dominanta pe ecran.** Un singur buton primar vizibil per
|
||
context (ex. „Trimite la RAR"). Restul sunt secundare/ghost.
|
||
6. **Tinte de atins generoase pe touch, sobre pe desktop.** Vezi scara de control.
|
||
|
||
---
|
||
|
||
## 2. Tokeni
|
||
|
||
### 2.1 Culoare (variabile CSS, 4 teme)
|
||
|
||
Paleta e definita pe `:root` (dark, default) si suprascrisa pe `[data-theme="light|petrol"]`.
|
||
`auto` se rezolva la light/dark dupa `prefers-color-scheme`. **Nu folosi culori hardcodate;
|
||
foloseste mereu variabilele.** Pentru tente, `color-mix(in srgb, var(--x) N%, transparent|var(--card))`.
|
||
|
||
| Token | Rol | dark | light | petrol |
|
||
|-------|-----|------|-------|--------|
|
||
| `--bg` | fundal pagina | `#0f1218` | `#f5f7fa` | `#0e1416` |
|
||
| `--card` | suprafata card/meniu | `#181c24` | `#ffffff` | `#161e20` |
|
||
| `--ink` | text principal | `#e6e9ef` | `#1a1d24` | `#e6e9ef` |
|
||
| `--muted` | text secundar | `#8b93a7` | `#5c6473` | `#8b93a7` |
|
||
| `--line` | borduri/separatoare | `#262b36` | `#e2e5ea` | `#232c2e` |
|
||
| `--accent` | actiune primara / link | `#2E74D6` | `#1F66C9` | `#0E7C7B` |
|
||
| `--ok` | succes / trimis | `#2FBF8F` | `#15803d` | `#2FBF8F` |
|
||
| `--warn` | atentie / de verificat | `#E0A93B` | `#b45309` | `#E0A93B` |
|
||
| `--err` | eroare / distructiv | `#E05D5D` | `#dc2626` | `#E05D5D` |
|
||
|
||
Accentul light (`#1F66C9`) e ales pentru contrast AA pe alb (5.51:1). Orice text colorat
|
||
pe `--card` trebuie sa ramana >= 4.5:1 in toate cele 3 palete.
|
||
|
||
### 2.2 Tipografie
|
||
|
||
Font: **IBM Plex Sans** (UI), **IBM Plex Mono** (VIN, coduri, ID-uri). Self-hosted, `latin-ext`
|
||
pentru diacritice, `font-display:swap`. Greutati disponibile: 400, 500, 700.
|
||
|
||
Scara (px / weight) — folosita consecvent, nu inventa marimi noi:
|
||
|
||
| Rol | size | weight | note |
|
||
|-----|------|--------|------|
|
||
| Titlu pagina (header) | 20 (desktop) / 17 (mobil) | 700 | letter-spacing -.01em |
|
||
| Titlu sectiune / card | 15 | 600 | `h2.sec` |
|
||
| Subtitlu / `h3` | 14 | 600 | |
|
||
| Corp / controale | 14 | 400/500 | inputuri, butoane |
|
||
| Eticheta camp, link card | 13 | 400/500 | `.cardlink`, label form |
|
||
| Secundar / meta | 12 | 400 | text muted, sub-linii |
|
||
| Micro (coduri, badge) | 11 | 500/700 | mono pentru coduri |
|
||
|
||
Numerele tabulare: `font-variant-numeric: tabular-nums` pe tabele (aliniere coloane).
|
||
Coduri/VIN/ID: `font-family: "IBM Plex Mono"`.
|
||
|
||
### 2.3 Spatiere
|
||
|
||
Scara 4px: **4, 6, 8, 10, 12, 14, 16, 20, 24**. Padding card desktop `16px 20px`, mobil `16px`.
|
||
Gap intre carduri `14–16px`. Gap intre controale pe o linie `8–12px`.
|
||
|
||
### 2.4 Radius
|
||
|
||
| Valoare | Uz |
|
||
|---------|-----|
|
||
| `6px` | controale: butoane, input, select |
|
||
| `7–8px` | carduri-rand, meniuri, butoane icon |
|
||
| `10px` | carduri de sectiune |
|
||
| `12px` | modal (desktop) |
|
||
| `99px` | pill-uri, badge-uri, bara de progres |
|
||
|
||
### 2.5 Elevatie
|
||
|
||
Plat implicit (border `1px solid var(--line)`). Umbra DOAR pentru elemente plutitoare:
|
||
meniuri/kebab `0 8px 24px rgba(0,0,0,.18)`, modal `0 16px 48px rgba(0,0,0,.35)`.
|
||
|
||
---
|
||
|
||
## 3. Breakpoints
|
||
|
||
Un singur prag conceptual mobil la **768px**; un prag de densitate la **1024px**.
|
||
|
||
| Interval | Numit | Regula |
|
||
|----------|-------|--------|
|
||
| `>= 1024px` | desktop | layout complet; aplica si compactarile globale (wizard) |
|
||
| `768–1024px` | tableta | **card-uri** pentru tabelele actionabile (Trimiteri, Preview, Mapari), UN card pe rand (nu 2/rand); tabelele dense read-only raman cu scroll contained |
|
||
| `< 768px` | mobil | un card pe rand, o coloana, tinte touch 44px |
|
||
|
||
CSS custom properties NU functioneaza in `@media`; pragul se scrie literal
|
||
(`@media (max-width:767px)`, `@media (max-width:1024px)`). Reutilizeaza aceste praguri,
|
||
nu introduce altele noi.
|
||
|
||
---
|
||
|
||
## 4. Scara de control (tinte de atins)
|
||
|
||
| Context | min-height | Uz |
|
||
|---------|-----------|-----|
|
||
| Touch (`< 768px`) | **44px** | orice buton/link/select interactiv |
|
||
| Desktop standard | **36px** | butoane, icon-btn, cardlink, intrari meniu |
|
||
| Compact (desktop) | **32px** | kebab summary, butoane pager, pill-cat |
|
||
|
||
Pe desktop nu fortam 44px peste tot (devine greoi); pe mobil da. Latimea butoanelor:
|
||
**auto, nu full-width**, cu exceptia butonului primar de actiune dintr-o bara dedicata
|
||
(ex. „Trimite la RAR" in bara sticky, „Salveaza si continua").
|
||
|
||
---
|
||
|
||
## 5. Componente
|
||
|
||
### 5.1 Butoane — sistem unificat
|
||
|
||
Patru variante. Toate: `font:inherit` (IBM Plex Sans), `font-weight:500`, `border-radius:6px`,
|
||
`padding:8px 14px` (desktop), tinta conform scarii de control. Tranzitie `filter/background .15s`.
|
||
|
||
| Varianta | Clasa | Fundal | Text | Bordura | Uz |
|
||
|----------|-------|--------|------|---------|-----|
|
||
| Primar | `.btn` (default `<button>`) | `--accent` | `#fff` | `--accent` | actiunea dominanta |
|
||
| Secundar | `.btn-secondary` | transparent | `--ink` | `--line` | actiuni neutre (Editeaza, Filtreaza) |
|
||
| Ghost | `.btn-ghost` | transparent | `--accent` | transparent | actiuni tertiare/linkuri-actiune |
|
||
| Distructiv | `.btn-danger` | transparent | `--err` | `--err` | Sterge; hover → fundal `--err`, text `#fff` |
|
||
|
||
**Iconite in butoane:** label text + iconita optionala la stanga (16px, `fill:currentColor`,
|
||
`aria-hidden`). **Butoanele icon-only sunt interzise pentru actiuni cu text echivalent**
|
||
(ex. Salveaza/Sterge in tabele) — au cauzat „bloc colorat cu iconita invizibila" pe mobil.
|
||
Cand spatiul e strans, foloseste un grup compact `[ Salveaza ] [ Sterge ]` cu text scurt,
|
||
nu doua blocuri full-width unul sub altul. Icon-only ramane permis DOAR pentru: comutator
|
||
tema, hamburger cont, kebab, inchidere modal — toate cu `aria-label`.
|
||
|
||
Stari: `:hover` → `filter:brightness(1.08)` (primar) sau `background:var(--line)` (secundar/ghost);
|
||
`:focus-visible` → `outline:2px solid var(--accent); outline-offset:2px`; `:disabled` →
|
||
`opacity:.45; cursor:default`. Stare „dirty" (modificari nesalvate) pe butonul de salvare:
|
||
fundal `--accent`.
|
||
|
||
### 5.2 Card
|
||
|
||
`background:var(--card); border:1px solid var(--line); border-radius:10px`. Carduri de
|
||
sectiune cu titlu `h2.sec` (15/600). Carduri-rand (lista pe mobil/tableta) cu radius 8–10px,
|
||
stivuite vertical, gap intern 7–8px.
|
||
|
||
### 5.3 Tabel → card-uri (responsive)
|
||
|
||
Tabelele **actionabile** (Trimiteri, Preview import, Mapari) devin card-uri sub 1024px.
|
||
Regula de card (vezi §3): NU folosi pattern-ul „eticheta cu `min-width` fix + valoare in
|
||
flex" — sparge valorile pe verticala. In schimb:
|
||
|
||
- **Stivuieste**: eticheta mica deasupra valorii (`display:block`), SAU
|
||
- **Card semantic**: linie titlu (identificator + stare), linii secundare mici. Preferat
|
||
pentru liste lungi (Trimiteri, Preview).
|
||
|
||
Listele actionabile (Trimiteri, Preview, Mapari) raman **O COLOANA (un card pe rand)** pe
|
||
TOT intervalul sub 1024px — nu se foloseste grila 2/rand. Decizie confirmata cu userul
|
||
(gate 2026-06-27): simplitate si consecventa primeaza fata de densitate pe tableta.
|
||
|
||
Tabelele **dense read-only** (Jurnal, Nomenclator, Admin) raman tabel cu scroll orizontal
|
||
**contained in card** (`.tablewrap { overflow-x:auto }`), nu se cardifica.
|
||
|
||
### 5.4 Stepper / wizard import — COMPACT pe toate latimile
|
||
|
||
Patru pasi: Incarca fisier · Potriveste coloanele · Verifica · Confirma trimiterea.
|
||
|
||
- **Desktop**: o bara slim orizontala — pastila numar (sau ✓) + titlu scurt pe O linie,
|
||
pasul activ evidentiat. **Fara paragraf de ajutor inalt** in bara (ajutorul, daca e
|
||
nevoie, e text mic sub bara, o singura linie). Inaltime tinta ~44px, nu blocuri inalte.
|
||
- **Tableta/mobil**: colapsat la o singura linie — `Pasul N din 4 · <Titlu>` + bara de
|
||
progres (`height:5px; border-radius:99px`, umplere `--accent` la `N/4`). Ajutorul pasului
|
||
activ sub bara, text 12px muted.
|
||
|
||
Niciodata 4 coloane egale cu text — se taie/se rupe pe ecrane inguste.
|
||
|
||
### 5.5 Pill-uri si badge-uri
|
||
|
||
Stare: `.pill` 12px, radius 99px, cu clasa de culoare (`.s-ok/.s-warn/...`). Filtre de
|
||
stare: `.pill-cat` (contur inactiv, umplere activa pe culoarea categoriei). Badge contor:
|
||
cerc 18px, `--err`, text alb 11/700.
|
||
|
||
### 5.6 Formulare
|
||
|
||
Label 12–13px muted deasupra controlului. Input/select: `--bg`, bordura `--line`, radius 6px,
|
||
padding `7px 10px`. Pe mobil controalele de formular din sectiunile de continut sunt
|
||
full-width (tinta 44px). Pe desktop pastreaza latimi rezonabile (`select` max ~340px).
|
||
|
||
### 5.7 Modal
|
||
|
||
Desktop: dialog centrat `max-width:680px`, radius 12px, backdrop `rgba(0,0,0,.55)`,
|
||
scroll intern. Mobil (`< 768px`): full-screen (fara colturi/umbra), buton inchidere 44px,
|
||
focus-trap + scroll-lock + `inert` pe `<main>`.
|
||
|
||
---
|
||
|
||
## 6. Accesibilitate (obligatoriu)
|
||
|
||
- Contrast text >= 4.5:1 (normal), >= 3:1 (>=18px bold) in toate cele 3 palete.
|
||
- Stare comunicata prin text, nu doar culoare.
|
||
- `:focus-visible` vizibil pe tot ce e interactiv (outline `--accent`).
|
||
- Tinte touch >= 44px pe mobil.
|
||
- Icon-only obligatoriu cu `aria-label`; SVG decorativ `aria-hidden="true"`.
|
||
- Modale: `role="dialog"`, `aria-modal`, focus-trap, focus return pe trigger.
|
||
- `prefers-reduced-motion`: scurteaza/elimina tranzitiile non-esentiale.
|
||
|
||
---
|
||
|
||
## 7. Pentru planurile de design (cum se foloseste acest fisier)
|
||
|
||
Inainte de orice propunere vizuala:
|
||
1. Citeste acest fisier integral. Foloseste DOAR tokenii de aici (culoare, type, radius, spatiu).
|
||
2. Verifica fiecare ecran la 360 / 768 / 1024 / 1280px.
|
||
3. Aplica compactarile globale (wizard, butoane) si pe desktop, nu doar pe mobil.
|
||
4. Respecta „un singur primar per context" si scara de control.
|
||
5. Daca o propunere cere un token nou (culoare/marime/radius), justifica si adauga-l AICI
|
||
in acelasi PR — nu introduce valori ad-hoc in template.
|
||
|
||
Stadiul de implementare a regulilor responsive se urmareste in PRD-ul activ
|
||
(`docs/prd/prd-5.13-responsive-compact.md`) si in `docs/ROADMAP.md`.
|