Decisions from plan-design-review and plan-eng-review: - Two-accent system: amber = state (nav, pills), blue = action (buttons) - JetBrains Mono selective: codes/numbers only, text uses DM Sans - Dark mode now in scope for Commit 0.5 - Add TODOS.md with deferred P2 items Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
325 lines
12 KiB
Markdown
325 lines
12 KiB
Markdown
# Design System — GoMag Vending
|
|
|
|
## Product Context
|
|
- **What this is:** Internal admin dashboard for importing web orders from GoMag e-commerce into ROA Oracle ERP
|
|
- **Who it's for:** Ops/admin team who monitor order sync daily, fix SKU mappings, check import errors
|
|
- **Space/industry:** Internal tools, B2B operations, ERP integration
|
|
- **Project type:** Data-heavy admin dashboard (tables, status indicators, sync controls)
|
|
|
|
## Aesthetic Direction
|
|
- **Direction:** Industrial/Utilitarian — function-first, data-dense, quietly confident
|
|
- **Decoration level:** Minimal — typography and color do the work. No illustrations, gradients, or decorative elements. The data IS the decoration.
|
|
- **Mood:** Command console. This tool says "built by someone who respects the operator." Serious, efficient, warm.
|
|
- **Anti-patterns:** No purple gradients, no 3-column icon grids, no centered-everything layouts, no decorative blobs, no stock-photo heroes
|
|
|
|
## Typography
|
|
|
|
### Font Stack
|
|
- **Display/Headings:** Space Grotesk — geometric, slightly techy, distinctive `a` and `g`. Says "engineered."
|
|
- **Body/UI:** DM Sans — clean, excellent readability, good tabular-nums for inline numbers
|
|
- **Data/Tables:** JetBrains Mono — order IDs, CODMATs, status codes align perfectly. Tables become scannable.
|
|
- **Code:** JetBrains Mono
|
|
|
|
### Loading
|
|
```html
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&family=JetBrains+Mono:wght@400;500;600&family=Space+Grotesk:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
```
|
|
|
|
### CSS Variables
|
|
```css
|
|
--font-display: 'Space Grotesk', sans-serif;
|
|
--font-body: 'DM Sans', sans-serif;
|
|
--font-data: 'JetBrains Mono', monospace;
|
|
```
|
|
|
|
### Type Scale
|
|
| Level | Size | Weight | Font | Usage |
|
|
|-------|------|--------|------|-------|
|
|
| Page title | 18px | 600 | Display | "Panou de Comanda" |
|
|
| Section title | 16px | 600 | Display | Card headers |
|
|
| Label/uppercase | 12px | 500 | Display | Column headers, section labels (letter-spacing: 0.04em) |
|
|
| Body | 14px | 400 | Body | Paragraphs, descriptions |
|
|
| UI/Button | 13px | 500 | Body | Buttons, nav links, form labels |
|
|
| Data cell | 13px | 400 | Data | Codes, IDs, numbers, sums, dates (NOT text names — those use Body font) |
|
|
| Data small | 12px | 400 | Data | Timestamps, secondary data |
|
|
| Code/mono | 11px | 400 | Data | Inline code, debug info |
|
|
|
|
## Color
|
|
|
|
### Approach: Two-accent system (amber state + blue action)
|
|
Every admin tool is blue. This one uses amber — reads as "operational" and "attention-worthy."
|
|
- **Amber (--accent):** Navigation active state, filter pill active, accent backgrounds. "Where you are."
|
|
- **Blue (--info):** Primary buttons, CTAs, actionable links. "What you can do."
|
|
- Primary buttons (`btn-primary`) stay blue for clear action hierarchy.
|
|
|
|
### Light Mode (default)
|
|
```css
|
|
:root {
|
|
/* Surfaces */
|
|
--bg: #F8F7F5; /* warm off-white, not clinical gray */
|
|
--surface: #FFFFFF;
|
|
--surface-raised: #F3F2EF; /* hover states, table headers */
|
|
--card-shadow: 0 1px 3px rgba(28,25,23,0.1), 0 1px 2px rgba(28,25,23,0.06);
|
|
|
|
/* Text */
|
|
--text-primary: #1C1917; /* warm black */
|
|
--text-secondary: #57534E; /* warm gray */
|
|
--text-muted: #78716C; /* labels, timestamps */
|
|
|
|
/* Borders */
|
|
--border: #E7E5E4;
|
|
--border-subtle: #F0EFED;
|
|
|
|
/* Accent — amber */
|
|
--accent: #D97706;
|
|
--accent-hover: #B45309;
|
|
--accent-light: #FEF3C7; /* amber backgrounds */
|
|
--accent-text: #92400E; /* text on amber bg */
|
|
|
|
/* Semantic */
|
|
--success: #16A34A;
|
|
--success-light: #DCFCE7;
|
|
--success-text: #166534;
|
|
|
|
--warning: #CA8A04;
|
|
--warning-light: #FEF9C3;
|
|
--warning-text: #854D0E;
|
|
|
|
--error: #DC2626;
|
|
--error-light: #FEE2E2;
|
|
--error-text: #991B1B;
|
|
|
|
--info: #2563EB;
|
|
--info-light: #DBEAFE;
|
|
--info-text: #1E40AF;
|
|
|
|
--cancelled: #78716C;
|
|
--cancelled-light: #F5F5F4;
|
|
}
|
|
```
|
|
|
|
### Dark Mode
|
|
Strategy: invert surfaces, reduce accent saturation ~15%, keep semantic colors recognizable.
|
|
|
|
```css
|
|
[data-theme="dark"] {
|
|
--bg: #121212;
|
|
--surface: #1E1E1E;
|
|
--surface-raised: #2A2A2A;
|
|
--card-shadow: 0 1px 3px rgba(0,0,0,0.4), 0 1px 2px rgba(0,0,0,0.3);
|
|
|
|
--text-primary: #E8E4DD; /* warm bone white */
|
|
--text-secondary: #A8A29E;
|
|
--text-muted: #78716C;
|
|
|
|
--border: #333333;
|
|
--border-subtle: #262626;
|
|
|
|
--accent: #F59E0B;
|
|
--accent-hover: #D97706;
|
|
--accent-light: rgba(245,158,11,0.12);
|
|
--accent-text: #FCD34D;
|
|
|
|
--success: #16A34A;
|
|
--success-light: rgba(22,163,74,0.15);
|
|
--success-text: #4ADE80;
|
|
|
|
--warning: #CA8A04;
|
|
--warning-light: rgba(202,138,4,0.15);
|
|
--warning-text: #FACC15;
|
|
|
|
--error: #DC2626;
|
|
--error-light: rgba(220,38,38,0.15);
|
|
--error-text: #FCA5A5;
|
|
|
|
--info: #2563EB;
|
|
--info-light: rgba(37,99,235,0.15);
|
|
--info-text: #93C5FD;
|
|
|
|
--cancelled: #78716C;
|
|
--cancelled-light: rgba(120,113,108,0.15);
|
|
}
|
|
```
|
|
|
|
### Status Color Mapping
|
|
| Status | Dot Color | Badge BG | Glow |
|
|
|--------|-----------|----------|------|
|
|
| IMPORTED | `--success` | `--success-light` | none (quiet when healthy) |
|
|
| ERROR | `--error` | `--error-light` | `0 0 8px 2px rgba(220,38,38,0.35)` |
|
|
| SKIPPED | `--warning` | `--warning-light` | `0 0 6px 2px rgba(202,138,4,0.3)` |
|
|
| ALREADY_IMPORTED | `--info` | `--info-light` | none |
|
|
| CANCELLED | `--cancelled` | `--cancelled-light` | none |
|
|
| DELETED_IN_ROA | `--cancelled` | `--cancelled-light` | none |
|
|
|
|
**Design rule:** Problems glow, success is calm. The operator's eye is pulled to rows that need action.
|
|
|
|
## Spacing
|
|
- **Base unit:** 4px
|
|
- **Density:** Comfortable — not cramped, not wasteful
|
|
- **Scale:**
|
|
|
|
| Token | Value | Usage |
|
|
|-------|-------|-------|
|
|
| 2xs | 2px | Tight internal gaps |
|
|
| xs | 4px | Icon-text gap, badge padding |
|
|
| sm | 8px | Compact card padding, table cell padding |
|
|
| md | 16px | Standard card padding, section gaps |
|
|
| lg | 24px | Section spacing |
|
|
| xl | 32px | Major section gaps |
|
|
| 2xl | 48px | Page-level spacing |
|
|
| 3xl | 64px | Hero spacing (rarely used) |
|
|
|
|
## Layout
|
|
|
|
### Approach: Grid-disciplined, full-width
|
|
Tables with 8+ columns and hundreds of rows need every pixel of width.
|
|
|
|
- **Nav:** Horizontal top bar, fixed, 48px height. Active tab has amber underline (2px).
|
|
- **Content max-width:** None on desktop (full-width for tables), 1200px for non-table content
|
|
- **Grid:** Single-column layout, cards stack vertically
|
|
- **Breakpoints:**
|
|
|
|
| Name | Width | Columns | Behavior |
|
|
|------|-------|---------|----------|
|
|
| Desktop | >= 1024px | Full width | All features visible |
|
|
| Tablet | 768-1023px | Full width | Nav labels abbreviated, tables scroll horizontally |
|
|
| Mobile | < 768px | Single column | Bottom nav, cards stack, condensed views |
|
|
|
|
### Border Radius
|
|
| Token | Value | Usage |
|
|
|-------|-------|-------|
|
|
| sm | 4px | Buttons, inputs, badges, status dots |
|
|
| md | 8px | Cards, dropdowns, modals |
|
|
| lg | 12px | Large containers, mockup frames |
|
|
| full | 9999px | Pills, avatar circles |
|
|
|
|
## Motion
|
|
- **Approach:** Minimal-functional — only transitions that aid comprehension
|
|
- **Easing:** enter(ease-out) exit(ease-in) move(ease-in-out)
|
|
- **Duration:**
|
|
|
|
| Token | Value | Usage |
|
|
|-------|-------|-------|
|
|
| micro | 50-100ms | Button hover, focus ring |
|
|
| short | 150-250ms | Dropdown open, tab switch, color transitions |
|
|
| medium | 250-400ms | Modal open/close, page transitions |
|
|
| long | 400-700ms | Only for sync pulse animation |
|
|
|
|
- **Sync pulse:** The live sync dot uses a 2s infinite pulse (opacity 1 → 0.4 → 1)
|
|
- **No:** entrance animations, scroll effects, decorative motion
|
|
|
|
## Mobile Design
|
|
|
|
### Navigation
|
|
- **Bottom tab bar** replaces top horizontal nav on screens < 768px
|
|
- 5 tabs: Dashboard, Mapari, Lipsa, Jurnale, Setari
|
|
- Each tab: icon (Bootstrap Icons) + short label below
|
|
- Active tab: amber accent color, inactive: `--text-muted`
|
|
- Height: 56px, safe-area padding for notched devices
|
|
- Fixed position bottom, with `padding-bottom: env(safe-area-inset-bottom)`
|
|
|
|
```css
|
|
@media (max-width: 767px) {
|
|
.top-navbar { display: none; }
|
|
.bottom-nav {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 56px;
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
background: var(--surface);
|
|
border-top: 1px solid var(--border);
|
|
display: flex;
|
|
justify-content: space-around;
|
|
align-items: center;
|
|
z-index: 1000;
|
|
}
|
|
.main-content {
|
|
padding-bottom: 72px; /* clear bottom nav */
|
|
padding-top: 8px; /* no top navbar */
|
|
}
|
|
}
|
|
```
|
|
|
|
### Dashboard — Mobile
|
|
- **Sync card:** Full width, stacked vertically
|
|
- Status + controls row wraps to 2 lines
|
|
- Sync button full-width at bottom of card
|
|
- Last sync info wraps naturally
|
|
- **Orders table:** Condensed card view instead of horizontal table
|
|
- Each order = a compact card showing: status dot + ID + client name + total
|
|
- Tap to expand: shows date, factura, full details
|
|
- Swipe left on card: quick action (view error details)
|
|
- **Filter bar:** Horizontal scrollable chips instead of dropdowns
|
|
- Period selector: pill chips (1zi, 7zi, 30zi, Toate)
|
|
- Status filter: colored chips matching status colors
|
|
- **Touch targets:** Minimum 44x44px for all interactive elements
|
|
|
|
### Orders Mobile Card Layout
|
|
```
|
|
┌────────────────────────────────┐
|
|
│ ● CMD-47832 2,450.00 RON│
|
|
│ SC Automate Express SRL │
|
|
│ 27.03.2026 · FCT-2026-1847 │
|
|
└────────────────────────────────┘
|
|
```
|
|
- Status dot (8px, left-aligned with glow for errors)
|
|
- Order ID in JetBrains Mono, amount right-aligned
|
|
- Client name in DM Sans
|
|
- Date + factura in muted data font
|
|
|
|
### SKU Mappings — Mobile
|
|
- Each mapping = expandable card
|
|
- Collapsed: SKU + product name + type badge (KIT/SIMPLU)
|
|
- Expanded: Full CODMAT list with quantities
|
|
- Search: Full-width sticky search bar at top
|
|
- Filter: Horizontal scrollable type chips
|
|
|
|
### Logs — Mobile
|
|
- Timeline view instead of table
|
|
- Each log entry = timestamp + status icon + summary
|
|
- Tap to expand full log details
|
|
- Infinite scroll with date separators
|
|
|
|
### Settings — Mobile
|
|
- Standard stacked form layout
|
|
- Full-width inputs
|
|
- Toggle switches for boolean settings (min 44px touch target)
|
|
- Save button sticky at bottom
|
|
|
|
### Gestures
|
|
- **Pull to refresh** on Dashboard: triggers sync status check
|
|
- **Swipe left** on order card: reveal quick actions
|
|
- **Long press** on SKU mapping: copy CODMAT to clipboard
|
|
- **No swipe navigation** between pages (use bottom tabs)
|
|
|
|
### Mobile Typography Adjustments
|
|
| Level | Desktop | Mobile |
|
|
|-------|---------|--------|
|
|
| Page title | 18px | 16px |
|
|
| Body | 14px | 14px (no change) |
|
|
| Data cell | 13px | 13px (no change) |
|
|
| Data small | 12px | 12px (no change) |
|
|
| Table header | 12px | 11px |
|
|
|
|
### Responsive Images & Icons
|
|
- Use Bootstrap Icons throughout (already loaded via CDN)
|
|
- Icon size: 16px desktop, 20px mobile (larger touch targets)
|
|
- No images in the admin interface (data-only)
|
|
|
|
## Decisions Log
|
|
| Date | Decision | Rationale |
|
|
|------|----------|-----------|
|
|
| 2026-03-27 | Initial design system created | Created by /design-consultation. Industrial/utilitarian aesthetic with amber accent, Space Grotesk + DM Sans + JetBrains Mono. |
|
|
| 2026-03-27 | Amber accent over blue | Every admin tool is blue. Amber reads as "operational" and gives the tool its own identity. Confirmed by Claude subagent ("Control Room Noir" also converged on amber). |
|
|
| 2026-03-27 | JetBrains Mono for data tables | Both primary analysis and subagent independently recommended monospace for data tables. Scannability win outweighs the ~15% wider columns. |
|
|
| 2026-03-27 | Warm tones throughout | Off-white (#F8F7F5) instead of clinical gray. Warm black text instead of blue-gray. Makes the tool feel handcrafted. |
|
|
| 2026-03-27 | Glowing status dots for errors | Problems glow (box-shadow), success is calm. Operator's eye is pulled to rows that need action. Inspired by subagent's "LED indicator" concept. |
|
|
| 2026-03-27 | Full mobile design | Bottom nav, card-based order views, touch-optimized gestures. Supports quick-glance usage from phone. |
|
|
| 2026-03-27 | Two-accent system | Blue = action (buttons, CTAs), amber = state (nav active, filter active). Clear hierarchy. |
|
|
| 2026-03-27 | JetBrains Mono selective | Mono font only for codes, IDs, numbers, sums, dates. Text names use DM Sans for readability. |
|
|
| 2026-03-27 | Dark mode in scope | CSS variables + toggle + localStorage. All DESIGN.md dark tokens implemented in Commit 0.5. |
|