Skip to content

Design quality — rubrică screenshot (Constructor / agenți)

Rubrică observabilă pe o singură captură (sau pe un set de capturi pe viewport) pentru a judeca layout-urile generate de AI în Constructor și pentru a corecta agentul.

Nu e un BlockKind. Completează: layout.md (grilă), global-styles.md (accent / font), pages.md (pagini), AGENTS.md.

Surse de adevăr (calibrare vizuală): design/GDS Portal.dc.html, design/src/GStack/*.dc.html, design/src/GPay/*.dc.html, projects/gds-core/src/lib/layout-system.ts, tokens.ts, css.ts.

Machine-readable: design-quality.json — ids, severități, praguri (pentru prompturi / review automat).


UnitateValoare canonicăObservabil pe imagine
Celulă grilă8px (GDS_GRID_CELL)Estimare din rail / gutters
Coloane conținut12Span-uri: 3 / 4 / 6 / 8 / 12
Rail sidenav (desktop)30 celule ≈ 240px (ref. 236–250px)Lățime bandă stângă
Padding conținut4 celule = 32px (ref. 24–34px)Spațiu între rail și primul bloc; dreapta artboard
Gutter2 celule = 16px (ref. 14–16px)Spațiu între carduri pe același rând
Gap vertical între blocuri2 celule = 16px (±8px)Distanță între marginile exterioare ale blocurilor
Artboard desktop1920×1080Dacă e vizibil frame-ul Constructor

Aria de conținut (cu rail): începe la ~col 34 (rail 30 + padding 4), se termină la ~col 236 (padding dreapta 4) → lățime ≈ 202 celule ≈ 1616px pe board 1920.

Toleranță screenshot: ±1 celulă (±8px) pe aliniere; ±2 celule pe ritm vertical. Orice criteriu sub „Pass” = eșec la acel id.

Verdict pagină (desktop):

  • FAIL dacă există ≥1 blocker, sau ≥2 major;
  • WARN dacă 1 major și 0 blockers;
  • PASS dacă doar minor / zero eșecuri.

  1. Checklist review — parcurge tabelul de mai jos pe o captură; notează id + pass/fail.
  2. Corecție agent — pentru fiecare eșec, trimite fraza din coloana Corecție agent (sau din design-quality.json → agentFix).

Checklist — criterii (id · măsură · prag · severitate)

Section titled “Checklist — criterii (id · măsură · prag · severitate)”
IdCriteriuCum se măsoarăPassSeveritateCorecție agent
ALIGN.LEFTMargine stângă comună a conținutuluiTrasează o linie verticală pe muchia stângă a page-header / KPI / chart / table. Distanța față de muchia dreaptă a rail-ului = padding.Toate blocurile de conținut (non-floating) pornesc pe aceeași linie ±8px; padding față de rail ∈ 24–40px (ideal 32).blockerAliniază toate blocurile de conținut la aceeași coloană stângă a content area (gdsContentArea); padding exterior 4 celule (32px) după rail.
ALIGN.RIGHTMargine dreaptă comunăMuchia dreaptă a rândurilor full / a perechilor care umplu 12 coloane.Diff între muchiile drepte ale rândurilor „pline” ≤ 16px. Rândurile cu span < 12 trebuie să aibă sibling pe același rând (vezi DEAD.ROW).blockerPăstrează o muchie dreaptă comună: rândurile full (span 12) și perechile 8+4 / 6+6 / 4×3 trebuie să ajungă la același content.right. Nu lăsa panouri care „se strâng” spre stânga pe pagină.
ALIGN.RAILRail vs conținut — fără overlapIntersecție vizuală sidenav ∩ conținut; text tăiat de rail.Zero overlap; conținutul nu intră sub / peste sidenav.blockerMută conținutul în dreapta rail-ului (30 celule). Nu plasa blocuri la col < railRight + padding.
ALIGN.CHROMEChrome pe lățimea disponibilăTopbar / brand-bar / site-nav: stânga = după rail (sau 0 fără rail); dreapta = muchia artboard.Chrome span pe toată lățimea lângă rail; fără „insulă” îngustă.majorChrome (topbar / brand-bar / site-nav) pe span 12 în aria chrome (fără padding-ul de conținut).
IdCriteriuCum se măsoarăPassSeveritateCorecție agent
GRID.SPANSpan-uri din setul canonicEstimare lățime bloc / lățime content ≈ k/12.Span ∈ {3,4,6,8,12}. KPI = span 12 cu 3–4 carduri egale.majorFolosește doar span-uri 3/4/6/8/12 via layout:{span}. KPI pe 12; chart principal 8 + panou 4; nu inventa lățimi arbitare.
GRID.GUTTERGuttere orizontale egaleSpațiu între carduri KPI / panouri pe același rând.Gap ∈ 14–18px (ideal 16); variație între gap-uri pe același rând ≤ 4px.majorGutter 2 celule (16px) între toate panourile din același rând.
GRID.RHYTHM8Snap pe ritmul de 8pxPoziții / dimensiuni estimate.Margini și gap-uri multipli de ~8px (±4px).minorSnap pe grila de 8px; nu folosi spațieri „libere” (ex. 11px, 23px).
GRID.PAIRPairing 8+4 / 6+6Rând cu ≥2 panouri combinabile.Suma span-urilor pe rând = 12 (ex. 8+4, 6+6, 4+4+4, 3×4). Un singur panou combinabil (donut/activity) pe rând fără sibling = eșec (legate de DEAD.ROW).blockerNu lăsa donut-chart / activity / panouri span-4 singure pe rând. Perechează: line-chart|bar-chart (8) + donut-chart|activity (4) pe același rând.
IdCriteriuCum se măsoarăPassSeveritateCorecție agent
DEAD.ROWGol dreapta pe un rând de conținutunused% = (contentRight − rowContentRight) / contentWidth × 100. Exclude: constrained centrat (form/auth), floating (toast/chat/drawer).unused% ≤ 8% (~≤1 coloană / ≤16px din validate).blocker dacă unused% ≥ 25%; major dacă 8% < unused% < 25%.Umple rândul până la marginea dreaptă: span 12 sau pereche a cărei sumă e 12. Gol ≥25% din lățimea de conținut pe dreapta e interzis.
DEAD.NARROWBlocuri care se îngustează pe verticalăCompară lățimea blocului N cu blocul full/pair de deasupra.Un bloc de conținut mai îngust cu ≥25% față de rândul plin de deasupra, fără sibling care umple restul → fail.blockerNu stivui un chart full-width apoi un donut îngust sub el. Fie ambele pe același rând (8+4), fie donut-ul e înlocuit/completat cu un panou care umple restul.
DEAD.BOARDTreime goală din boardBandă verticală goală pe dreapta conținutului, pe ≥2 rânduri.Nicio bandă goală ≥ 33% din lățimea de conținut pe ≥2 rânduri consecutive.blockerRedistribuie layout-ul: elimină coloana goală din dreapta; folosește toată content area pe fiecare rând de conținut.
IdCriteriuCum se măsoarăPassSeveritateCorecție agent
VERT.GAPGap constant între blocuriDistanțe între page-header → KPI → primary → secondary.Gap ∈ 12–24px (ideal 16); max−min pe pagină ≤ 12px.majorGap vertical 2 celule (16px) între toate blocurile de conținut consecutive.
VERT.CRAMPZone înghesuiteText lipit de bordură / carduri fără aer.Padding interior card ≥ 12px; gap < 8px între blocuri = fail.majorCrește spațierea: nu lipi blocurile; păstrează ≥16px între stack-uri.
VERT.ORPHANSpațiu orfan mareGol vertical anormal între două secțiuni (fără footer sticky).Gol vertical izolat ≤ 48px (6 celule) între secțiuni consecutive de conținut.minorElimină spațiile goale mari între secțiuni; împachetează stack-ul cu gap 16px.
IdCriteriuCum se măsoarăPassSeveritateCorecție agent
HIER.HEADERPrezență page-headerTitlu de pagină vizibil sub chrome.Dashboard / listă / overview: există page-header (titlu ≥ ~22px, descriere opțională).majorAdaugă page-header cu titlu + descriere scurtă imediat sub chrome, înainte de KPI.
HIER.LANDINGTitlu landing sub navigarePe o pagină publică, compară muchia de jos a `site-navbrand-barcu muchia de sus ahero`.Există navigare de sus; hero-ul începe complet sub ea, cu titlul integral vizibil. hero poate înlocui page-header, nu și chrome-ul.blocker
HIER.SCALEScară tipograficăTitlu pagină vs titluri card vs body vs meta.Titlu pagină > titlu card > body; fără două „H1” concurente pe același viewport.minorUn singur titlu de pagină dominant; titlurile de card rămân secundare (--gds-fs-*).
HIER.KPI_FIRSTKPI înaintea detaliuluiOrdine verticală.Dacă există KPI și chart/table: KPI deasupra primary visual.majorOrdine: page-header → kpi-row → chart/table principal → panouri secundare.
HIER.PRIMARYUn vizual principalAria ocupată / poziție.Exact un bloc „primary” pe primul ecran util (chart sau table), nu 3 chart-uri egale fără ierarhie.minorUn vizual principal (span 8 sau 12); restul secundar (span 4) sau sub fold.
IdCriteriuCum se măsoarăPassSeveritateCorecție agent
DENS.KPINumăr carduri KPINumără cardurile pe primul rând KPI.Desktop: 3 sau 4 carduri egale pe un rând (2 pe tablet; 1–2 pe phone). 1 card pe tot rândul desktop = fail major.majorKPI row cu 3–4 carduri egale pe desktop (span 12).
DENS.ROWBlocuri pe rândNumără panourile pe un rând de conținut.1 (full), 2 (8+4 / 6+6) sau 3–4 (egale). ≥5 panouri pe un rând desktop = overcrowded.majorMax 4 panouri pe rând; preferă 8+4 sau 4×3.
DENS.SPARSERând prea aerisitUn singur card mic pe un rând lat.Același prag ca DEAD.ROW / DEAD.NARROW.blockerVezi DEAD.ROW: umple rândul sau mută panoul lângă un sibling.
IdCriteriuCum se măsoarăPassSeveritateCorecție agent
COMP.ORDERSecvența canonicăCitește de sus în jos.App: sidenav? → topbar → page-header → KPI → primary → secondary → footer?. Public: site-nav|brand-bar → hero|page-header → content → footer?. Inversiunile sau conținutul la row 0 înaintea chrome-ului = fail.majorRespectă sloturile din layout.md: chrome de deschidere primul, titlul al doilea, footer ultimul.
COMP.FOOTERFooter dacă e prezentPoziție.Footer jos, span full chrome; nu intercalat între KPI și chart.minorsite-footer doar la finalul stack-ului, pe lățimea chrome.

H. Consistență cross-page (necesită ≥2 capturi)

Section titled “H. Consistență cross-page (necesită ≥2 capturi)”
IdCriteriuCum se măsoarăPassSeveritateCorecție agent
XPAGE.RAILAcelași railLățime / stil sidenav pe paginile aceluiași produs.Diff lățime rail ≤ 16px; același tip de shell (light/dark).majorPăstrează același sidenav width (~240px) și același pattern de shell pe toate paginile proiectului.
XPAGE.CONTENTAceeași content areaStânga/dreapta conținut.Aliniere stângă/dreaptă identică ±8px între pagini.majorAceeași content area pe toate paginile; nu schimba padding-ul per pagină.
XPAGE.HEADERAcelași pattern de antetPrezență topbar + page-header.Același chrome + același tip de page-header pe paginile de app (nu marketing).minorReutilizează același topbar + page-header pattern pe paginile de produs.

I. Adaptare responsive (capturi tablet 820 / phone 430)

Section titled “I. Adaptare responsive (capturi tablet 820 / phone 430)”
IdCriteriuCum se măsoarăPassSeveritateCorecție agent
RESP.COLStivuire pe viewport îngustPe phone: coloane.Phone 430: o singură coloană de conținut. Tablet 820: max 2 coloane; KPI 2×2.blockerPe layouts.phone: toate blocurile span full / o coloană. Pe tablet: densitate redusă, secundare stivuite.
RESP.NAVNavigare adaptatăRail vizibil?Tablet/foldable: icon-rail sau colaps. Phone: top app bar / bottom-menu — nu rail 240px permanent pe 430.blockerPe phone colapsează sidenav-ul (top bar + sheet); pe tablet folosește icon-rail.
RESP.OVERFLOWFără scroll orizontalConținut tăiat / scrollbar orizontal.Niciun overflow orizontal; nimic tăiat de frame.blockerElimină overflow-ul orizontal; reflow pe lățimea frame-ului.
RESP.TOUCHȚinte tactileButoane / itemi nav.Înălțime tap ≥ 40px (ideal 44) pe phone.majorMărește țintele tactile la ≥40px pe phone.
IdCriteriuCum se măsoarăPassSeveritateCorecție agent
COMP.GLYPHIconițe = simboluriText vizibil în sloturile de icon.Niciun literal de tip home, bell, settings, user, search, menu afișat ca text în loc de glyph/SVG.blockerIconurile trebuie să fie glyph-uri monochrome / SVG (ex. ▣ ☰ ⚙), nu numele iconului ca string vizibil.
COMP.OVERLAPText / blocuri care se suprapunIntersecții vizibile.Zero overlap text∩text sau text∩UI.blockerRepară overlap-ul: repoziționează blocurile (packGdsBlock / fără dreptunghiuri care se intersectează).
COMP.CLIPConținut tăiatText/chart tăiat de bordură sau de frame.Niciun clip pe label-uri, KPI values, legende.majorMărește rowSpan / lățimea până ce textul și legenda sunt complete.
COMP.DATADate populatePlaceholder-uri goale.KPI cu valori numerice; chart cu serie; table cu ≥3 rânduri; fără „— — —” / „Lorem” dominant.majorPopulează date reale (faker / dataset); nu lăsa carduri sau chart-uri goale.
IdCriteriuCum se măsoarăPassSeveritateCorecție agent
COLOR.ACCENTUn accent de brandActive nav, butoane primary, highlight.O singură familie de accent (indigo/emerald/amber/rose/blue/teal); status colors doar pe delta/badge.majorAccent doar prin meta.accent → --gds-accent / --gds-primary. Fără hex hardcodat pe blocuri.
COLOR.CONTRASTContrast textText pe fundal.Text principal lizibil pe surface/shell; fără gri deschis pe alb pentru body.majorFolosește --gds-text-normal / ink tokens; asigură contrast adecvat.
COLOR.CLASHCulori discordantePete neon / gradient random pe carduri.Fără fundaluri hardcodate în afara surface / accent-soft / ink / status-soft.minorElimină culorile hardcodate; folosește tokens din css.ts / tokens.ts.
TYPE.FONTFamilie coerentăUniformitate.O familie din FontName pe tot ecranul (mono doar pe cod/ID).minormeta.font unic pe proiect; mono doar pentru ID-uri / log lines.

Bifează pe screenshot. Oricare bifă = eșec la id-ul mapat (severitate din checklist).

Anti-patternSemnal pe imagineId-uri
Coloană goală ~⅓ din board pe dreaptaBandă albă verticală ≥33% content widthDEAD.BOARD, DEAD.ROW
Blocuri care se îngustează în josFull → mid → narrow, fără siblingsDEAD.NARROW, ALIGN.RIGHT
Chart full + donut singur sub elDonut <50% din lățimea chart-ului de deasupraGRID.PAIR, DEAD.NARROW, DENS.SPARSE
Lățimi inconsistente pe stackMuchii drepte „în scară”ALIGN.RIGHT, GRID.SPAN
Icon name ca text (home, bell)Cuvinte în loc de simboluri în nav/KPICOMP.GLYPH
Conținut peste sidenavText/carduri sub sau prin railALIGN.RAIL
Gap-uri haotice4px apoi 40px între aceleași tipuri de blocuriVERT.GAP
Fără page-headerKPI / chart încep direct sub topbarHIER.HEADER, COMP.ORDER
Rail 240px pe phone 430Conținut zdrobit; overflowRESP.NAV, RESP.OVERFLOW

Din layout.md / blockLayoutIntent — pe desktop, un rând trebuie să arate ca unul din:

PresetSpan-uriFolosit pentru
Full12page-header, kpi-row, table, alert, search, CTA
Primary + side8 + 4line/bar/hbar + donut/activity/deadline
Split egal6 + 6două panouri echilibrate
Triadă4 + 4 + 4trei carduri
Quad3 + 3 + 3 + 3patru carduri compacte
Constrained6 centratform, auth-gate, profile, receipt
Floating4 endtoast, chat, drawer — excluse din DEAD.*

Referințele hand-made (GLog, GPay) folosesc KPI 4× egale + rând ~1.55fr 1fr (≈8+4), gutter 14–16px, padding 26–28px, rail 236px — mapate pe Constructor la 16 / 32 / 240.


ProbăAșteptare
AI output cunoscut-defect (donut îngust, gol dreapta, stack îngustat)FAIL pe DEAD.ROW, DEAD.NARROW, ALIGN.RIGHT, GRID.PAIR (blocker)
Referință hand-made GLog / GPay / GDS PortalPASS (cel mult minor pe toleranță screenshot)

Dacă un review trece AI-defectul sau pică referința, pragurile DEAD.* / ALIGN.RIGHT / GRID.PAIR trebuie strânse — nu relaxate.

Scor calibrare — AI-defect (screenshot Constructor GLog)

Section titled “Scor calibrare — AI-defect (screenshot Constructor GLog)”

Măsură pe imagine: KPI + line-chart pe lățime comună; donut pe rând separat, ~⅔ din lățimea de deasupra → unused% ≈ 30–40% pe dreapta (≥25% → blocker).

IdRezultatNotă
ALIGN.LEFTpassStânga comună header/KPI/chart
ALIGN.RIGHTFAIL blockerMuchia dreaptă a donut ≠ muchia KPI/line
ALIGN.RAILpassFără overlap pe sidenav
GRID.PAIRFAIL blockerDonut combinabil singur pe rând
DEAD.ROWFAIL blockerunused% ≥ 25%
DEAD.NARROWFAIL blockerÎngustare ≥25% față de rândul plin de deasupra
DEAD.BOARDFAIL sau borderlineBandă goală pe ≥1 rând; dacă e pe un singur rând, DEAD.ROW e suficient
VERT.*passGap-uri între secțiuni aparent regulate
HIER.* / COMP.ORDERpassHeader → KPI → chart → secondary
DENS.KPIpass4 carduri
DENS.SPARSEFAIL blockerRând donut aerisit
COMP.GLYPHpassGlyph-uri, nu home/bell ca text
COMP.DATApassValori + serii populate
COLOR.*passAccent blue / status pe delta

Verdict: FAIL (≥4 blockers pe aliniere / spațiu mort / pairing).

Scor calibrare — referință hand-made design/src/GStack/GLog.dc.html

Section titled “Scor calibrare — referință hand-made design/src/GStack/GLog.dc.html”

Din markup: rail 236px, main padding 26×28, KPI repeat(4,1fr) gap 16, rând principal 1.55fr 1fr gap 16 (umple lățimea), iconițe SVG, ordine canonică.

IdRezultat
ALIGN.LEFT / ALIGN.RIGHT / ALIGN.RAILpass
GRID.SPAN / GRID.GUTTER / GRID.PAIRpass (≈8+4)
DEAD.ROW / DEAD.NARROW / DEAD.BOARDpass (unused% ≈ 0)
VERT.GAP / HIER.* / COMP.ORDER / DENS.KPIpass
COMP.GLYPH / COMP.DATApass
RESP.*pass în CSS (max-width:880 / 480: stack, drawer) — pe captură desktop N/A

Verdict: PASS.