- Accent: #f97316 (orange) → #60a5fa/#2563eb (electric blue) - Info: new cyan (#67e8f9/#0891b2) since blue took the accent slot - Warning: #eab308 (yellow) → #fbbf24/#d97706 (amber reclaimed) - Surfaces: deeper charcoal range for better layer separation - Full light mode semantic color variants specified - Based on competitive research: no MSP tool uses this blue register Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
441 lines
15 KiB
Markdown
441 lines
15 KiB
Markdown
# ResolutionFlow Design System v6
|
|
|
|
> **Status:** ACTIVE — This document is the single source of truth for all frontend design decisions.
|
|
> **Supersedes:** All previous design system docs including v5 (ember orange accent), `DESIGN_SYSTEM_GUIDE.md`, `UI-DESIGN-SYSTEM.md`, `REBRAND-IMPLEMENTATION-GUIDE.md`, and any `COMPONENT_EXAMPLES.md` files.
|
|
> **Last Updated:** March 29, 2026
|
|
|
|
---
|
|
|
|
## Design Philosophy
|
|
|
|
ResolutionFlow uses a **flat, high-contrast dark theme** inspired by Sentry and PostHog. The aesthetic is premium, clean, and minimal — no glass morphism, no backdrop blur, no ambient orbs, no gradient backgrounds on surfaces. The accent color (electric blue) appears in ≤5% of the UI. Cool blue accent on deep charcoal surfaces creates high contrast and technical confidence — blue conveys trust, precision, and reliability, fitting for a troubleshooting tool that MSP engineers depend on during outages. Every design decision prioritizes **readability over decoration**.
|
|
|
|
**Dual-mode design:** Dark mode is the default. Light mode is fully specified — all colors use CSS custom properties so theming is a variable swap, not a rewrite. Semantic colors shift to darker variants (Tailwind 400→600) in light mode to maintain WCAG AA contrast.
|
|
|
|
---
|
|
|
|
## Color System
|
|
|
|
All colors are defined as CSS custom properties in `index.css` inside the `@theme` block (Tailwind v4) or `:root` / `.dark` blocks (Tailwind v3).
|
|
|
|
### Dark Mode (Default) — Deep Charcoal Palette
|
|
|
|
```
|
|
Page background: #16181f
|
|
Sidebar background: #0e1016
|
|
Card background: #1e2028
|
|
Card hover: #252830
|
|
Input background: #252830
|
|
Code background: #12141a
|
|
Elevated surface: #2a2d38
|
|
Surface raised: #303442
|
|
|
|
Text primary: #e2e5eb
|
|
Text heading: #f0f2f5
|
|
Text secondary: #848b9b
|
|
Text muted: #4f5666
|
|
Text rail label: #e2e5eb
|
|
|
|
Border default: #2a2e3a
|
|
Border hover: #3d4252
|
|
|
|
Accent (blue): #60a5fa
|
|
Accent hover: #3b82f6
|
|
Accent dim (10%): rgba(96,165,250,0.10)
|
|
Accent text: #93c5fd
|
|
Accent glow (15%): rgba(96,165,250,0.15)
|
|
|
|
Success: #34d399
|
|
Success dim: rgba(52,211,153,0.10)
|
|
Warning (amber): #fbbf24
|
|
Warning dim: rgba(251,191,36,0.10)
|
|
Danger: #f87171
|
|
Danger dim: rgba(248,113,113,0.10)
|
|
Info (cyan): #67e8f9
|
|
Info dim: rgba(103,232,249,0.10)
|
|
```
|
|
|
|
### Light Mode
|
|
|
|
```
|
|
Page background: #f3f4f7
|
|
Sidebar background: #ffffff
|
|
Card background: #ffffff
|
|
Card hover: #f8f9fb
|
|
Input background: #eef0f4
|
|
Code background: #f5f6f9
|
|
Elevated surface: #e8eaef
|
|
Surface raised: #dde0e7
|
|
|
|
Text primary: #1a1d24
|
|
Text heading: #0d0f13
|
|
Text secondary: #5a6274
|
|
Text muted: #8b92a1
|
|
|
|
Border default: #dde0e7
|
|
Border hover: #c5c9d3
|
|
|
|
Accent: #2563eb
|
|
Accent hover: #1d4ed8
|
|
Accent dim: rgba(37,99,235,0.07)
|
|
Accent text: #1d4ed8
|
|
Accent glow: rgba(37,99,235,0.10)
|
|
|
|
Success: #059669
|
|
Success dim: rgba(5,150,105,0.07)
|
|
Warning: #d97706
|
|
Warning dim: rgba(217,119,6,0.07)
|
|
Danger: #dc2626
|
|
Danger dim: rgba(220,38,38,0.07)
|
|
Info: #0891b2
|
|
Info dim: rgba(8,145,178,0.07)
|
|
```
|
|
|
|
### What NOT To Use
|
|
|
|
- No glass morphism (`backdrop-filter: blur`)
|
|
- No gradient backgrounds on cards or surfaces
|
|
- No ambient orbs or floating glow elements
|
|
- No `bg-white/[0.04]` opacity-based backgrounds
|
|
- No ember orange accent (`#f97316` / `#ea580c` / `#fdba74`) — replaced by blue in v6
|
|
- No `text-gradient-brand` utility — replaced by solid `accent-text` color
|
|
- No `glass-card`, `glass-stat`, `glass-card-glow` CSS utilities
|
|
|
|
---
|
|
|
|
## Typography
|
|
|
|
### Font Stack
|
|
|
|
| Role | Font | Weights | CSS Variable |
|
|
|------|------|---------|-------------|
|
|
| Body text | IBM Plex Sans | 400, 500, 600, 700 | `--font-sans` / `font-sans` |
|
|
| Headings | Bricolage Grotesque | 600, 700, 800 | `--font-heading` / `font-heading` |
|
|
| Code / Monospace | JetBrains Mono | 400, 500 | `--font-mono` / `font-mono` |
|
|
|
|
### Typography Scale
|
|
|
|
| Element | Size | Weight | Color | Letter Spacing |
|
|
|---------|------|--------|-------|---------------|
|
|
| Page title (h1) | 22px | 700 (Bricolage) | text-heading | -0.03em |
|
|
| Section title | 15px | 600 (Bricolage) | text-heading | normal |
|
|
| Card title | 14px | 600 (IBM Plex) | text-heading | normal |
|
|
| Body text | 14px | 400 (IBM Plex) | text-primary | normal |
|
|
| Secondary text | 13px | 400 (IBM Plex) | text-secondary | normal |
|
|
| Label / hint | 12px | 500 (IBM Plex) | text-muted | normal |
|
|
| Nav section header | 10px | 600 (IBM Plex) | text-muted | 1.2px, uppercase |
|
|
| Rail icon label | 10px | 500 (IBM Plex) | text-rail-label | normal |
|
|
| Code | 12px | 400 (JetBrains) | text-primary | normal |
|
|
| Stat number | 28px | 700 (Bricolage) | text-heading | -0.03em |
|
|
| Badge | 11px | 550 (IBM Plex) | varies | normal |
|
|
|
|
### What NOT To Use
|
|
|
|
- No Inter, Plus Jakarta Sans, or Outfit — these are deprecated
|
|
- No `font-label` utility — use `font-mono` for monospace or `font-sans` at small size
|
|
- No font sizes below 10px
|
|
|
|
---
|
|
|
|
## Layout Architecture
|
|
|
|
### App Shell
|
|
|
|
The app uses a CSS Grid layout with two states:
|
|
|
|
**Icon Rail (Default):**
|
|
```
|
|
[icon-rail: 72px] [main-content: 1fr]
|
|
```
|
|
|
|
**Pinned Sidebar:**
|
|
```
|
|
[full-sidebar: 260px] [main-content: 1fr]
|
|
```
|
|
|
|
### Icon Rail Sidebar
|
|
|
|
The default navigation is a narrow icon rail (72px) with:
|
|
- Logo mark at top (30px square, gradient background, lightning bolt icon)
|
|
- Nav items as vertical column: icon (20px) + label text (10px) underneath
|
|
- Dividers between nav sections
|
|
- User avatar at bottom
|
|
- Pin/expand button below avatar
|
|
|
|
**Hover behavior:** Hovering a rail item opens a flyout panel (220px) to the right of the rail with sub-navigation items for that section. The flyout stays open while the cursor is on either the rail item or the flyout panel.
|
|
|
|
**Pinned state:** Clicking the pin button expands to a traditional 260px sidebar with full text labels, section headers, badges, and the active left-bar accent. An unpin button in the header returns to the icon rail.
|
|
|
|
### Active Nav Indicator
|
|
|
|
- **Icon rail:** `accent-dim` background on the item, `accent-text` color on icon and label
|
|
- **Pinned sidebar:** Same as above, plus a 3px left border (`border-radius: 0 3px 3px 0`) in `accent` color
|
|
|
|
### Main Content Area
|
|
|
|
- Padding: 28px top/bottom, 36px left/right
|
|
- Max content width: not constrained (fills available space)
|
|
- Page title: Bricolage Grotesque, 22px, weight 700
|
|
|
|
---
|
|
|
|
## Component Patterns
|
|
|
|
### Stat Cards
|
|
|
|
```
|
|
Background: bg-card
|
|
Border: 1px solid border-default
|
|
Border-left: 3px solid [varies by position - accent, success, warning, info]
|
|
Border-radius: 8px
|
|
Padding: 18px 16px
|
|
```
|
|
|
|
- Label: 11px, uppercase, 600 weight, text-muted
|
|
- Value: 28px, Bricolage Grotesque 700, text-heading
|
|
- Delta: 12px, 500 weight, success/danger color with ↑/↓ prefix
|
|
|
|
### Cards
|
|
|
|
```
|
|
Background: bg-card
|
|
Border: 1px solid border-default
|
|
Border-radius: 8px
|
|
Padding: 20px
|
|
Hover: border-color transitions to border-hover
|
|
```
|
|
|
|
No shadows. No gradients. No glow effects.
|
|
|
|
### Flow List Items
|
|
|
|
```
|
|
Layout: flex row, 12px gap
|
|
Padding: 10px 8px
|
|
Border-bottom: 1px solid border-default (divider style, not bordered cards)
|
|
Hover: bg-card-hover
|
|
```
|
|
|
|
- Icon: 34px square, border-radius 5px, semantic dim background + colored stroke
|
|
- Name: 13px, 500 weight, text-heading
|
|
- Meta: 11.5px, text-muted
|
|
- Badge: right-aligned status badge
|
|
|
|
### Badges
|
|
|
|
```
|
|
Font: 11px, 550 weight
|
|
Padding: 3px 9px
|
|
Border-radius: 20px (pill)
|
|
```
|
|
|
|
| Type | Background | Text Color |
|
|
|------|-----------|------------|
|
|
| Accent | accent-dim | accent-text |
|
|
| Success | success-dim | success |
|
|
| Warning | warning-dim | warning |
|
|
| Danger | danger-dim | danger |
|
|
| Info | info-dim | info |
|
|
|
|
### Form Inputs
|
|
|
|
```
|
|
Background: bg-input
|
|
Border: 1px solid border-default
|
|
Border-radius: 5px
|
|
Padding: 9px 12px
|
|
Font: 13px, IBM Plex Sans
|
|
Focus: border-color accent, box-shadow 0 0 0 2px accent-dim
|
|
Placeholder: text-muted
|
|
```
|
|
|
|
### Buttons
|
|
|
|
**Primary:**
|
|
```
|
|
Background: accent (#60a5fa dark / #2563eb light)
|
|
Color: #fff
|
|
Border: none
|
|
Border-radius: 5px
|
|
Padding: 9px 16px
|
|
Font: 13px, 550 weight
|
|
Hover: accent-hover (#3b82f6 dark / #1d4ed8 light), box-shadow 0 2px 12px accent-glow, translateY(-1px)
|
|
Active: translateY(0), box-shadow 0 0 4px accent-glow
|
|
```
|
|
|
|
**Ghost:**
|
|
```
|
|
Background: transparent
|
|
Color: text-secondary
|
|
Border: 1px solid border-default
|
|
Hover: bg-elevated, text-primary, border-hover
|
|
```
|
|
|
|
### Code Blocks
|
|
|
|
```
|
|
Background: bg-code (#12141a)
|
|
Border: 1px solid border-default
|
|
Border-radius: 8px
|
|
Padding: 18px 20px
|
|
Font: JetBrains Mono, 12px, line-height 1.7
|
|
```
|
|
|
|
**Syntax colors (dark mode):**
|
|
|
|
| Token | Color |
|
|
|-------|-------|
|
|
| Comment | #4a5568 |
|
|
| Keyword | #c792ea |
|
|
| Function/Cmdlet | #82aaff |
|
|
| String | #c3e88d |
|
|
| Variable | #93c5fd (accent-text) |
|
|
| Parameter | #8c93a4 |
|
|
| Number | #f78c6c |
|
|
|
|
### Chips / Tags
|
|
|
|
```
|
|
Font: 11.5px, 500 weight
|
|
Padding: 4px 11px
|
|
Border-radius: 20px
|
|
Background: accent-dim
|
|
Color: accent-text
|
|
```
|
|
|
|
---
|
|
|
|
## Logo
|
|
|
|
- **Mark:** 30-32px square, border-radius 8px, `linear-gradient(135deg, #3b82f6, #60a5fa)`, white lightning bolt SVG
|
|
- **Wordmark:** "ResolutionFlow" in Bricolage Grotesque, 16-17px, weight 700, text-heading color
|
|
- **Combined:** Mark + wordmark horizontally, 10px gap
|
|
|
|
---
|
|
|
|
## Spacing System
|
|
|
|
- Component internal gaps: 6px, 8px, 12px, 14px, 16px
|
|
- Card padding: 20px
|
|
- Section gaps: 24px between major sections
|
|
- Page padding: 28px vertical, 36px horizontal
|
|
- Stat grid gap: 12px
|
|
- Two-column gap: 16px
|
|
- Nav item padding: 8px 10px (pinned), 8px 4px (rail)
|
|
|
|
---
|
|
|
|
## Border Radius
|
|
|
|
| Token | Value | Use |
|
|
|-------|-------|-----|
|
|
| radius-sm | 5px | Inputs, buttons, small elements |
|
|
| radius | 8px | Cards, stat cards, code blocks |
|
|
| radius-lg | 12px | Large cards, modals |
|
|
| radius-xl | 16px | Hero elements, CTA boxes |
|
|
| radius-pill | 100px | Badges, chips, toggle tracks |
|
|
|
|
---
|
|
|
|
## Shadows
|
|
|
|
Shadows communicate **interaction state**, not decoration. On dark backgrounds, traditional black shadows are invisible — use **brighter surfaces + faint accent glow** instead.
|
|
|
|
**Resting state:** No shadows. Elements are flat with 1px borders.
|
|
|
|
**Elevation on dark backgrounds (the principle):** Instead of shadow = darker, elevation = lighter. A "raised" element gets a brighter surface color (`bg-elevated` / `#2a2d38` or `bg-raised` / `#303442`) and optionally a very faint blue glow. This creates perceived depth through contrast.
|
|
|
|
**Hover state (buttons):** Lift effect with accent glow.
|
|
|
|
- Primary button hover: `0 2px 12px rgba(96,165,250,0.25)` + `translateY(-1px)` — blue glow
|
|
- Ghost button hover: brighter border (`border-hover`) + `translateY(-1px)`, no shadow
|
|
- Active/click: glow fades, element "presses down" to `translateY(0)`
|
|
|
|
**Active/selected state (tabs, toggles):** Elevated surface + faint accent glow.
|
|
|
|
- Active tab: `bg-elevated` + `box-shadow: 0 1px 4px rgba(96,165,250,0.08)` — class: `tab-active-shadow`
|
|
|
|
**Card hover lift (optional):** For clickable cards.
|
|
|
|
- Hover: brighter border + `0 2px 8px rgba(96,165,250,0.06)` + `translateY(-2px)` — class: `card-lift`
|
|
|
|
**Overlays:** Flyouts, dropdowns, modals get stronger shadows (they overlay lighter content).
|
|
|
|
- Drawer/flyout: `4px 0 12px rgba(0,0,0,0.2)`
|
|
- Dropdown: `0 4px 12px rgba(0,0,0,0.3)`
|
|
- Modal: `0 8px 24px rgba(0,0,0,0.4)`
|
|
|
|
**What NOT to do:**
|
|
|
|
- No `rgba(0,0,0,...)` shadows on resting elements (invisible on dark bg)
|
|
- No permanent decorative shadows
|
|
- No heavy glow effects — accent glow should be barely perceptible (≤ 0.1 opacity)
|
|
- No orange glow effects — all accent glows use blue rgba(96,165,250,...)
|
|
|
|
---
|
|
|
|
## Icons
|
|
|
|
All icons use Lucide React (`lucide-react` package).
|
|
- Default size: 16-18px
|
|
- Stroke width: 1.6-1.8
|
|
- Color: `currentColor` (inherits from parent text color)
|
|
- Nav icons: 20px at stroke-width 1.6
|
|
- Rail icon opacity: 0.6 default, 0.85 on hover, 1.0 when active
|
|
|
|
---
|
|
|
|
## Landing Page
|
|
|
|
The marketing landing page at `/` shares the same color system and typography but has its own layout (no sidebar, full-width sections). Key differences:
|
|
|
|
- Navigation: fixed top bar with logo, links, and CTAs
|
|
- Hero: centered layout with glow effect (radial gradient, accent at 15% opacity)
|
|
- Sections: 100px vertical padding, max-width 1120px container
|
|
- Section labels: JetBrains Mono, 12px, uppercase, accent-text color
|
|
- Section titles: Bricolage Grotesque, clamp(28px, 4vw, 42px), weight 800
|
|
- Pricing cards: same card pattern but with featured state (accent border + subtle glow)
|
|
- Product mockup: embedded in hero, shows the actual app UI with browser chrome
|
|
|
|
---
|
|
|
|
## Files That Define The Design System
|
|
|
|
These are the source-of-truth files in the codebase:
|
|
|
|
| File | What It Controls |
|
|
|------|-----------------|
|
|
| `frontend/src/index.css` | CSS variables, `@theme` block, base styles |
|
|
| `frontend/tailwind.config.js` (v3) or inline in index.css (v4) | Color tokens, font families, spacing extensions |
|
|
| `frontend/index.html` | Google Font imports |
|
|
| `DESIGN-SYSTEM.md` (this file) | Design decisions, component specs, rules |
|
|
|
|
---
|
|
|
|
## Deprecated Files — DO NOT Reference
|
|
|
|
These files contain outdated design information and should be ignored:
|
|
|
|
- `DESIGN_SYSTEM_GUIDE.md` — Old monochrome glass-morphism system
|
|
- `UI-DESIGN-SYSTEM.md` — Old workspace/purple gradient system
|
|
- `REBRAND-IMPLEMENTATION-GUIDE.md` — Old purple rebrand from Patherly
|
|
- `COMPONENT_EXAMPLES.md` — Old monochrome component patterns
|
|
- Any file referencing `glass-card`, `glass-stat`, `bg-gradient-brand`, or `text-gradient-brand`
|
|
- Any code using ember orange accent values (`#f97316`, `#ea580c`, `#fdba74`, `rgba(249,115,22,...)`) — migrate to blue accent
|
|
- Any code using old cyan accent values (`#22d3ee`, `#06b6d4`) for accent purposes — cyan is now the info color only
|
|
|
|
---
|
|
|
|
## Decisions Log
|
|
|
|
| Date | Decision | Rationale |
|
|
|------|----------|-----------|
|
|
| 2026-03-24 | Accent color changed from cyan (#22d3ee) to ember orange (#f97316) | Cyan caused contrast issues, felt generic "tech SaaS". Orange provides warmth against cold charcoal. |
|
|
| 2026-03-24 | Warning color shifted from amber (#fbbf24) to yellow (#eab308) | Orange accent would clash with amber warning. |
|
|
| 2026-03-24 | Synced DESIGN-SYSTEM.md to actual charcoal palette | Doc was behind — updated to match index.css. |
|
|
| 2026-03-29 | Accent changed from ember orange (#f97316) to electric blue (#60a5fa/#2563eb) | Orange did not test well with users — read as "budget/cautionary." Blue conveys trust and technical confidence. Electric blue is brighter than the corporate blues used by NinjaOne/ConnectWise/Datto, maintaining differentiation. Works on both dark and light backgrounds. |
|
|
| 2026-03-29 | Info color set to cyan (#67e8f9/#0891b2) | Blue accent freed the info slot. Cyan is visually distinct from accent blue (cooler/lighter) and intuitive for informational contexts. |
|
|
| 2026-03-29 | Warning reclaimed as amber (#fbbf24/#d97706) | Yellow (#eab308) was only needed to avoid clashing with orange accent. With blue accent, amber is the natural warning color again. |
|
|
| 2026-03-29 | Surfaces deepened for better layer separation | Page: #1a1c23→#16181f, Card: #22252e→#1e2028, Sidebar: #10121a→#0e1016. Wider range gives 4+ clear visual depth layers instead of 2. Added surface-raised (#303442) for hover/active states. |
|
|
| 2026-03-29 | Full light mode semantic colors specified | All semantic colors get light-mode variants at Tailwind 600 level (dark uses 400). Ensures WCAG AA contrast on white/light surfaces. |
|