Files
roa2web-service-auto/docs/DESIGN.md
Claude Agent 8234103884 fix(design): mobile receipt form layout + confidence badges + DESIGN.md
Fix mobile layout issues on /data-entry/create after OCR upload:
- CompactUploadZone action bar forced horizontal on mobile (was stacking
  vertically due to global .action-bar column rule in containers.css)
- TOTAL input stretches full width on mobile (was fixed 140px)
- Card/Cash/Alte payment inputs equal width via flex: 1 1 0%
- Extra-small (≤360px) fallback stacks payments vertically
- OCR confidence badges: fixed width (icon-only), hidden percentage text,
  hover opacity effect — prevents input misalignment
- OCRConfidenceIndicator: replace hardcoded colors with design tokens
  (green-100/800, yellow-100/800, red-100/800), add three-tier dark mode
- Smaller size-small badge variant (border-radius-sm, line-height: 1)

Create docs/DESIGN.md as design source of truth for /design-review,
/plan-design-review, and /frontend-design skills.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:40:42 +00:00

15 KiB
Raw Permalink Blame History

ROA2WEB Design System

Version: 1.0.0 | Updated: 2026-03-23 | Status: Source of Truth


1. Design Philosophy

ROA2WEB is an ERP application for accounting and financial data management. The design prioritizes:

  • Data density over whitespace — Users process hundreds of records daily; every pixel earns its space
  • Scan-friendly hierarchy — Bold totals, muted labels, color-coded sections guide the eye
  • Compact, not cramped — 32px input height, 8px gaps, systematic spacing scale
  • Professional restraint — No decorative elements, no hero sections, no gratuitous animation
  • Trust at the pixel level — Financial data demands precision; misaligned inputs erode confidence
  • System fonts for speed — No custom font loading; native OS typography feels fast and familiar
  • Progressive disclosure — Show summary first, reveal detail on demand (collapsible sections, tooltips, bottom sheets)

2. Visual Identity

Brand Colors

Role Token Hex (Light) Usage
Primary --color-primary #2563eb Actions, links, focus rings, active states
Primary Dark --color-primary-dark #1d4ed8 Hover states, pressed buttons
Success --color-success #059669 Approvals, positive values, confirmations
Warning --color-warning #d97706 Pending states, caution alerts, mismatches
Error --color-error #dc2626 Rejections, validation errors, negative values
Info --color-info #0891b2 Informational badges, OCR hints

Surface Hierarchy

Ground (#f8fafc) → Section → Card (#ffffff) → Overlay
  ↓ darkest             ↓ lightest       ↓ modal/dropdown

Each level uses progressively elevated surface tokens. In dark mode, the scale inverts (darker = lower, lighter = higher).

Token Light Dark Purpose
--surface-ground #f8fafc #0f172a Page background
--surface-card #ffffff #1e293b Card/container backgrounds
--surface-hover #f1f5f9 #334155 Hover states, chips
--surface-border #e2e8f0 #475569 Borders, dividers
--text-color #111827 #f9fafb Primary text
--text-color-secondary #6b7280 #d1d5db Labels, hints, metadata

Full palette reference: DESIGN_TOKENS.md


3. Color System

Semantic Color Roles

Always use semantic tokens, never raw hex values:

/* Backgrounds */
background: var(--surface-card);      /* Cards, modals */
background: var(--surface-ground);    /* Page background */
background: var(--surface-hover);     /* Hover states, chips */

/* Text */
color: var(--text-color);             /* Primary text */
color: var(--text-color-secondary);   /* Labels, hints */

/* Borders */
border-color: var(--surface-border);  /* Standard borders */

Status Color Scales

Each status has a 50-900 scale. Use 100 for backgrounds, 800 for text in light mode:

Status Background Text Border Use For
Success --green-100 --green-800 --green-300 Approvals, positive values, OCR high confidence
Warning --yellow-100 --yellow-800 --yellow-300 Pending, caution, OCR medium confidence
Error --red-100 --red-800 --red-300 Rejections, errors, OCR low confidence
Info --blue-100 --blue-800 --blue-300 Informational, OCR hints, categorization

OCR Confidence Colors

Level Threshold Background Text Icon
High >= 85% --green-100 --green-800 pi-check-circle
Medium >= 60% --yellow-100 --yellow-800 pi-exclamation-circle
Low < 60% --red-100 --red-800 pi-question-circle

Color-Coded Form Sections

  • Green background (--green-50): Financial values (TOTAL, payments, TVA)
  • Blue background (--blue-50): Categorization (expense type, description)
  • Cyan background (--cyan-50): Client/B2B information
  • No background: Standard form fields (supplier, document)

4. Typography

Font Stack

font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-family: var(--font-mono); /* For financial values, code */

Scale

Token Size Usage
--text-xs 12px Labels, badges, metadata, timestamps, hints
--text-sm 14px Table cells, form inputs, secondary text, buttons
--text-base 16px Body text, primary content (default)
--text-lg 18px Subheadings
--text-xl 20px Card titles, section headings
--text-2xl 24px Page titles, metric values, KPI numbers
--text-3xl 32px Dashboard hero numbers
--text-4xl 40px Reserved for exceptional emphasis

Weight Rules

Token Value Usage
--font-normal 400 Body text, table cells, descriptions
--font-medium 500 Labels, buttons, badges, emphasis
--font-semibold 600 Headings, financial totals, card titles
--font-bold 700 TOTAL labels, strong emphasis, alerts

Financial Numbers

All financial values use font-variant-numeric: tabular-nums for column alignment.


5. Spacing & Layout

Spacing Scale

Token Value Primary Use
--space-xs 4px Icon gaps, badge padding, tight internal spacing
--space-sm 8px Related item gaps, compact form spacing
--space-md 16px Standard component padding, section gaps
--space-lg 24px Card padding, section separation
--space-xl 32px Page margins, major separations
--space-2xl 48px Layout sections
--space-3xl 64px Page-level spacing

Form Layout Rules

  • Input height: 32px for compact forms, 40px for standalone forms
  • Input font: --text-sm (14px) for form inputs
  • Numeric inputs: text-align: right always
  • Labels: --text-xs (12px), --font-semibold, --text-color-secondary
  • Layout: Inline labels next to inputs on desktop, stacked on mobile
  • Row gaps: --space-sm (8px) between form rows
  • Row borders: 1px solid var(--surface-border) between rows

Breakpoints

Name Width Layout Behavior
Extra-small ≤360px Payment inputs stack vertically, minimal padding
Mobile ≤768px Single column, stacked forms, bottom sheets for filters
Tablet 769-1023px Hybrid layout, wider cards
Desktop ≥1024px Full multi-column, inline forms, side-by-side panels
Wide ≥1400px Max content width, centered layout

6. Component Patterns

Cards

/* Standard card */
background: var(--surface-card);
border-radius: var(--radius-md);    /* 8px */
padding: var(--space-lg);           /* 24px */
box-shadow: var(--shadow-sm);

/* Compact card (data-dense views) */
padding: var(--space-md);           /* 16px */

/* Metric/KPI card */
/* Icon + --text-2xl value + --text-xs label + trend indicator */

Buttons

  • Primary: --color-primary background, white text
  • Secondary: Outlined or text-only (severity="secondary")
  • Minimum touch target: 44x44px on mobile
  • Icon buttons: 32x32px on desktop, 44x44px on mobile

Tables (PrimeVue DataTable)

  • Separate Debit/Credit columns (never stacked in one cell)
  • Filter buttons on dedicated row below filters
  • Export exports ALL data, not just current page
  • All overrides in vendor/primevue-overrides.css — never use :deep() in components

Dropdowns in Compact Forms

Use dropdown-borderless class for inline dropdowns:

<Dropdown ... class="my-select dropdown-borderless" />

Full pattern reference: CSS_PATTERNS.md


7. Form Design

Receipt Form Layout (UnifiedReceiptForm)

Ultra-compact flat layout with color-coded sections:

┌─────────────────────────────────────────────┐
│ Furnizor [AutoComplete____] CUI [___] 🟢 ↻ │  ← white bg
├─────────────────────────────────────────────┤
│ OCR: Lidl Discount SRL (22891860)           │  ← blue-50 hint
├─────────────────────────────────────────────┤
│ [Bon fiscal ▾]    Nr. [___]  Data [___] 🟢  │  ← white bg
├─────────────────────────────────────────────┤
│ TOTAL [_140px_] 🟢   Card [_120px_]         │  ← green-50 bg
│                        Cash [_120px_]         │
│                        Alte [_120px_] 🟢      │
├─────────────────────────────────────────────┤
│ TVA: [19% ▾][___] [9% ▾][___]        🟢    │  ← white bg
├─────────────────────────────────────────────┤
│ [Cheltuiala... ▾]                            │  ← blue-50 bg
│ [Descriere...________________________]       │
├─────────────────────────────────────────────┤
│ Atasamente: [📄 bon.pdf ✕] []             │  ← white bg
└─────────────────────────────────────────────┘

OCR Confidence Badges

  • Placement: Inline, next to the input they describe
  • Display: Icon-only in compact form (percentage hidden, available via tooltip)
  • Sizing: Fixed reserved width (20px) to prevent input misalignment
  • Hover: opacity: 0.85 → 1 transition for discoverability
  • Interaction: cursor: help, tooltip shows full percentage on hover/tap

Input Conventions

/* All compact form inputs */
height: 32px;
padding: var(--space-xs) var(--space-sm);
font-size: var(--text-sm);
border: 1px solid var(--surface-border);
border-radius: var(--radius-sm);

/* Financial inputs additionally */
text-align: right;
font-variant-numeric: tabular-nums;

8. Mobile Strategy

Philosophy

MD3-inspired (Material Design 3) touch-first design. Mobile is not "desktop shrunk" — it gets intentional layout.

Required Components (ALL mobile views)

Component Location Purpose
MobileTopBar @shared/components/mobile/MobileTopBar.vue Fixed header (56px), title, actions
MobileBottomNav @shared/components/mobile/MobileBottomNav.vue Fixed footer (56px), tab navigation
BottomSheet @shared/components/mobile/BottomSheet.vue Filters, extended options (slides up)
MobileSelectionFooter @shared/components/mobile/MobileSelectionFooter.vue Batch actions when items selected

Content Padding

.mobile-content {
  padding-top: 56px;    /* MobileTopBar height */
  padding-bottom: 56px; /* MobileBottomNav height */
}

Mobile Form Rules

  • Full-width inputs: Stacked vertically, width: 100%
  • Payment inputs: Equal-width side-by-side (flex: 1 1 0%), stack on extra-small (≤360px)
  • Confidence badges: Icon-only, no percentage text
  • Filters: Always in BottomSheet, never inline
  • Selection actions: Always in MobileSelectionFooter, never in header
  • Upload zone: Reduced height (24px min) after file selection

Touch Targets

  • Minimum: 44x44px for all interactive elements (buttons, links, checkboxes)
  • Input font: 16px minimum to prevent iOS zoom
  • Active feedback: scale(0.98) on touch for responsive feel

Full mobile guide: MOBILE_PATTERNS.md


9. Dark Mode

Three-Tier System

Mode Trigger CSS Selector
Auto (default) OS preference @media (prefers-color-scheme: dark) + :root:not([data-theme])
Light User toggle [data-theme="light"] on <html>
Dark User toggle [data-theme="dark"] on <html>

CSS Priority

[data-theme="dark/light"]  >  @media (prefers-color-scheme)  >  :root (light default)

Implementation Pattern

/* Light mode (default) */
.component { background: var(--green-100); color: var(--green-800); }

/* Dark mode — explicit toggle */
[data-theme="dark"] .component {
  background: rgba(34, 197, 94, 0.2);
  color: var(--green-400);
}

/* Dark mode — auto (prefers-color-scheme) */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .component {
    background: rgba(34, 197, 94, 0.2);
    color: var(--green-400);
  }
}

Key Rules

  • Always use semantic tokens (--surface-card, --text-color) — they auto-adapt
  • Status colors: Use rgba() overlays in dark mode, not the inverted scale tokens
  • Persistence: localStorage['user-theme'] stores user choice
  • Toggle: Theme button in AppHeader.vue cycles auto → light → dark

Testing Checklist

  1. Click theme button in header (cycles auto → light → dark)
  2. DevTools → Rendering → Emulate CSS media → prefers-color-scheme: dark
  3. Verify all text remains readable
  4. Verify colored sections (green, blue) are visible but not harsh

10. Accessibility

Targets

  • WCAG 2.1 AA compliance
  • Color contrast: --color-text provides 16.9:1 ratio, --color-text-secondary provides 4.6:1

Focus States

outline: 2px solid var(--color-primary);
outline-offset: 2px;

Touch Targets

  • All interactive elements: minimum 44x44px on mobile
  • Added via min-height: 44px; min-width: 44px on touch devices

Heading Hierarchy

  • Sequential: h1 > h2 > h3 (no skipping levels)
  • One <h1> per page (page title)
  • <h2> for sections, <h3> for subsections

Screen Reader Support

  • .sr-only class for visually hidden but accessible text
  • ARIA landmarks on major regions
  • Meaningful alt text on all images

Reduced Motion

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

11. Reference Index

Document Purpose Read When
DESIGN_TOKENS.md Complete token reference with all variables Looking up specific token values
CSS_PATTERNS.md Reusable component CSS patterns Building or styling components
ONBOARDING_CSS.md CSS system quick start (5 min) New to the project's frontend
MOBILE_PATTERNS.md Mobile component library and patterns Building mobile views
ARCHITECTURE-DECISIONS.md Technical architecture decisions Understanding "why" behind choices

CSS File Structure

src/assets/css/
├── core/           # Foundation: variables, tokens, md3-tokens, reset, typography
├── layout/         # Grid, containers, navigation
├── components/     # Cards, buttons, tables, forms, stats
├── patterns/       # Interactive, dashboard, animations
├── utilities/      # Spacing, display, text, flex, colors
├── vendor/         # PrimeVue overrides (centralized, never :deep())
├── mobile.css      # Mobile optimizations (imported last)
└── main.css        # Entry point with import cascade