Dashboard Design System
Good dashboards are just clarity. Simple rules, great UI. This page codifies the recurring patterns observed across 12 production-grade admin dashboards (Classic, E-commerce, Sales, CRM, Project Management, File Manager, Crypto, Academy, Hospital Management, Website Analytics, Finance, Payment) into an authoritative, reusable design system.
Reference screenshots archived at wiki/assets/dashboards/ (24 images: 12 light + 12 dark).
Base Typography
| Role | Size | Weight | Notes |
|---|---|---|---|
| Page title | 24px | semibold (600) | Only place semibold appears reliably |
| Card title | 14px | medium (500) | Paired with 16px icon to the left |
| Hero stat | 28-36px | semibold (600) | The single number the card exists to communicate |
| Body / cell text | 14px | regular (400) | The base - everything defaults here |
| Secondary label | 13px | regular (400) | Muted color, never smaller than 12px |
| Badge / tag | 12px | medium (500) | All-caps optional, pill-shaped container |
The 14px rule. 14px is the base font size for dashboard UI. Not 16px (too editorial), not 13px (too dense for scanning). 14px lets stat cards, tables, and labels coexist without competing.
Letter spacing. Body text at 14px uses -0.2px letter-spacing. This tightens the default browser tracking just enough to feel intentional without hurting readability. Don't go tighter - -0.3px starts collapsing at small sizes.
Weight discipline. Three weights maximum: regular (400) for body, medium (500) for labels and card titles, semibold (600) only for page headings and hero stat numbers. Bold (700) is almost never used. If everything is bold, nothing is.
The AliGrids/@_heyrico dashboard artifact independently reinforces the same density contract: 14px base text, 16px base icons, 1/1.2/1.5px icon strokes, and regular/medium/rare semibold weights. The reviewed image is a dark finance dashboard with a quiet sidebar, search, notification badges, stat cards, and charts; the useful lesson is small, consistent primitives instead of oversized dashboard chrome. Source: X/@AliGrids and local image review, 2026-07-03
Tabular numbers. Every number that updates or compares uses font-variant-numeric: tabular-nums. KPIs, prices, percentages, table columns, dates. No exceptions.
Base Iconography
| Property | Value |
|---|---|
| Base size | 16px (in sidebar nav, card titles, action buttons) |
| Large | 20px (page-level actions, empty states) |
| Small | 14px (inside badges, inline with 13px text) |
| Stroke width - default | 1.5px |
| Stroke width - navigation | 1.5px |
| Stroke width - decorative | 1.2px (lighter, for visual accents in stat cards) |
| Stroke width - emphasized | 2px (rare - only active states or primary actions) |
| Library | Lucide React |
Optical alignment. Icons in sidebar nav items align to the text baseline, not the container center. The icon sits 12px from the left edge, 8-10px gap to the label text. Asymmetric SVGs (play, volume) need 1-2px nudges.
Layout Architecture
Shell Structure
┌──────────────────────────────────────────────────────┐
│ Sidebar (240px) │ Top Bar (56px height) │
│ │ ┌─────────────────────────────┐ │
│ Logo + Brand │ │ Page Title │ Date │ CTA │ │
│ Search │ ├─────────────────────────────┤ │
│ ───────────── │ │ │ │
│ Nav Group │ │ Stat Cards (row of 3-4) │ │
│ Active ███ │ │ │ │
│ Item │ ├──────────┬──────────────────┤ │
│ Item (6) │ │ │ │ │
│ ───────────── │ │ Chart │ Chart / List │ │
│ Nav Group │ │ │ │ │
│ Item │ ├──────────┴──────────────────┤ │
│ Item │ │ │ │
│ ───────────── │ │ Table / Transaction List │ │
│ User Avatar │ │ │ │
└──────────────────┴──────────────────────────────────┘
Dimensions
| Element | Value |
|---|---|
| Sidebar width | 240px (collapsed: 64px icon-only) |
| Top bar height | 56px |
| Content padding | 24px (outer), 16px (between cards) |
| Card gap | 16px (grid gap between all cards) |
| Card padding | 20-24px |
| Card radius | 8px (consistent across all card types) |
| Content max-width | None - fluid fill, sidebar constrains |
| Sidebar nav item height | 36-40px |
Grid
Stat cards at the top use a responsive grid: 4 columns on wide screens, 2 on medium, 1 on narrow. Below the stat row, content cards fill a 2-column or 3-column grid depending on the dashboard variant. The grid uses 16px gap uniformly.
Stat Cards
The single most repeated pattern across all 12 dashboards. Every dashboard opens with a row of 3-4 stat cards.
Anatomy
┌─────────────────────────────┐
│ [icon] Label [▲] │
│ │
│ $125,430 │
│ +12.5% compared to last mo │
│ │
│ [Transfer] [Request] │ ← optional actions
└─────────────────────────────┘
| Part | Spec |
|---|---|
| Icon | 16px, muted color, top-left next to label |
| Label | 14px medium, muted text color |
| Value | 28-36px semibold, primary text color |
| Delta | 13px regular, green (#10b981) positive / red (#ef4444) negative |
| Context | 13px regular, muted ("from last month", "vs last month") |
| Sparkline | Optional, 48px tall, below or beside the value |
Delta formatting. Always show direction: +12.5% or -3.1%. Use an upward/downward trend icon (12px) paired with the percentage. Green and red are the only delta colors - no orange, no yellow.
Value formatting. Large numbers use comma separators. Currency uses $ prefix and 2 decimal places for amounts under $1,000, no decimals above. Percentages show 1 decimal place. Use K and M suffixes above 10,000 and 1,000,000.
Charts
Chart Types by Use Case
| Type | When | Examples |
|---|---|---|
| Vertical bar | Period comparison, distribution | Revenue by day/week, income sources |
| Line | Trends over time | Exercise minutes, balance history |
| Area (filled line) | Volume trends | Daily sales, user activity |
| Donut / Ring | Composition, progress | Category split, completion %, budget allocation |
| Horizontal bar | Ranked comparison | Sales pipeline stages, traffic sources |
| Sparkline | Inline trend in stat card | Revenue trend, subscriber growth |
Chart Styling
| Property | Value |
|---|---|
| Bar corner radius | 4px top corners, 0 bottom |
| Bar width | 60-70% of available slot |
| Line stroke width | 2px |
| Area fill opacity | 0.1-0.15 |
| Grid lines | Horizontal only, 1px, muted border color |
| Axis labels | 12px regular, muted color |
| Tooltip | Card-style, 8px radius, subtle shadow |
| Legend | Below or inside chart, dot + label, 12px |
Color discipline. One primary color per chart. Secondary series use the same hue at lower opacity, or a single contrasting accent. Never more than 5 colors in one chart. Donut charts can use 4-5 distinct category colors.
Dark mode charts. Grid lines use rgba(255, 255, 255, 0.06). Bars and areas use slightly higher saturation than light mode to maintain contrast against dark backgrounds.
Sidebar Navigation
Shadcn's "50+ sidebars" anecdote is a useful warning: the sidebar is the product shell's shared contract, not a disposable component. Treat it like a design-system primitive with stable grouping, active-state semantics, collapse behavior, badges, keyboard/focus behavior, and product-area naming that can scale across many apps without every team inventing a cousin. Source: X/@shadcn, 2026-06-20
Structure
The sidebar has 3-4 sections, each with a group heading:
- Dashboards - the main dashboard views
- Apps - Kanban, Chat, Mail, Calendar, etc.
- Pages - Settings, Profile, Error pages
- Others - Help, Documentation
Specs
| Element | Spec |
|---|---|
| Group heading | 11-12px, uppercase, medium weight, muted color, 12px left padding |
| Nav item | 14px regular, 36px height, 12px left padding, 8px icon-label gap |
| Active item | Medium weight, primary text color, subtle background fill (8px radius) |
| Hover | Slightly lighter background fill |
| Icon | 16px, 1.5px stroke, muted color (active: primary) |
| Badge | Right-aligned, red dot or pill with count, 12px text |
| Chevron | Right-aligned, 14px, indicates expandable submenu |
| Section divider | 1px border, muted, 8px vertical margin |
| Bottom section | User avatar (32px), name (14px medium), email (12px muted) |
Collapse Behavior
Sidebar collapses to 64px icon-only rail. Icons center-align. Tooltip shows label on hover. Group headings hide. Active indicator becomes a vertical bar or dot.
Top Bar
[Sidebar Toggle] [Search ⌘K] [CTA] [🔔] [🌙] [⚙] [Avatar]
| Element | Spec |
|---|---|
| Height | 56px |
| Search | Input with ⌘K shortcut hint, ~400px wide, rounded, muted border |
| CTA | Primary button ("Download", "Get Pro"), 14px medium, always top-right |
| Icons | 16px, 1.5px stroke, 24px spacing between |
| Notification dot | Red, 8px, positioned top-right of bell icon |
| Avatar | 32px circle, right-aligned |
| Border | 1px bottom border, muted |
Empty States
Every view that can be empty needs an empty state. "No data" is not an empty state.
| Part | Spec |
|---|---|
| Illustration | 120-160px, muted/grayscale, centered above text |
| Heading | 16px medium, primary text color |
| Description | 14px regular, muted text, 1-2 lines max |
| CTA | Primary button below description, clear action verb ("Create project", "Import data") |
| Vertical spacing | 16px between illustration → heading → description → CTA |
The rule. Illustration + CTA, not just "No data." Empty states are onboarding moments - they tell users what belongs here and how to fill it. A table with zero rows shows the illustration stack. A chart with no data shows a placeholder with the CTA to configure the data source.
Tables
Anatomy
| Part | Spec |
|---|---|
| Header row | 13px medium, muted color, uppercase optional, bottom border |
| Body row | 14px regular, 48-52px height, bottom border (subtle) |
| Cell padding | 12-16px horizontal |
| Status badge | Pill shape, 12px medium, colored background at 10% opacity + text color |
| Actions | Icon buttons (16px), right-aligned, appear on hover or always visible |
| Pagination | Bottom of table, "Previous / Next" buttons + page indicator |
| Filter | Text input above table, or dropdown selects |
| Column selector | "Columns" dropdown button, right-aligned above table |
| Hover row | Subtle background tint |
| Checkbox | 16px, left column, for batch actions |
Status Badge Colors
| Status | Background | Text |
|---|---|---|
| Completed / Success | green-100 / green-500 | green-700 |
| In Progress | blue-100 / blue-500 | blue-700 |
| New / Pending | amber-100 / amber-500 | amber-700 |
| On Hold / Warning | orange-100 / orange-500 | orange-700 |
| Cancelled / Error | red-100 / red-500 | red-700 |
Color System
Light Mode
| Token | Value | Usage |
|---|---|---|
| Background | #ffffff | Page background |
| Surface | #ffffff | Card backgrounds (borders create separation) |
| Border | #e5e7eb | Card borders, dividers |
| Border muted | #f3f4f6 | Table row borders, subtle separators |
| Text primary | #09090b | Headings, stat values |
| Text secondary | #71717a | Labels, descriptions |
| Text muted | #a1a1aa | Timestamps, helper text |
| Accent | #18181b | CTA buttons, active sidebar |
Dark Mode
| Token | Value | Usage |
|---|---|---|
| Background | #09090b | Page background |
| Surface | #0f0f11 or #111113 | Card backgrounds |
| Border | #27272a | Card borders, dividers |
| Border muted | #1e1e21 | Subtle separators |
| Text primary | #fafafa | Headings, stat values |
| Text secondary | #a1a1aa | Labels, descriptions |
| Text muted | #71717a | Timestamps, helper text |
| Accent | #fafafa | CTA buttons (inverted from light) |
Semantic Colors (Both Modes)
| Token | Value | Usage |
|---|---|---|
| Positive | #10b981 | Revenue up, growth, success |
| Negative | #ef4444 | Revenue down, errors, decline |
| Info | #3b82f6 | Links, informational badges |
| Warning | #f59e0b | Attention, pending items |
One accent rule. Each dashboard variant uses at most one brand accent beyond the semantic colors. Finance uses amber for income. Crypto uses orange for Bitcoin. CRM uses green for deals. The accent never competes with the positive/negative semantic pair.
Dark Mode Card Shadows (The 1px Rule)
Every card in dark mode uses two shadows to create physicality:
box-shadow:
inset 0 1px 0 0 rgba(255, 255, 255, 0.02),
0 0px 0 0 rgba(0, 0, 0, 0.25);
Inner shadow (white at 2%, inset) simulates a top-edge catch-light. Drop shadow (black at 25%) grounds the card. Together they make a flat rectangle read as a physical surface. See Interface Micro-Polish for the full rationale.
Spacing System
| Token | Value | Usage |
|---|---|---|
gap-cards |
16px | Between all cards in the grid |
pad-card |
20-24px | Internal card padding |
pad-content |
24px | Main content area outer padding |
pad-sidebar |
12px horizontal | Sidebar internal padding |
gap-stat-parts |
4px | Between label and value in stat cards |
gap-icon-text |
8px | Icon to adjacent text (nav items, card titles) |
gap-section |
24px | Between major content sections |
All spacing uses 4px granularity. The 16px card gap is the rhythm unit - everything else is a multiple or fraction.
Motion
Dashboards are mostly static. Animation is reserved for:
- Sidebar collapse/expand - 200ms ease-out width transition
- Chart entrance - 300ms staggered bar/line draw on first load
- Tooltip appearance - 100ms opacity + translateY(4px)
- Page transitions - 150ms content fade on sidebar nav click
- Dropdown menus - 150ms scale(0.95) → scale(1) + opacity
No animation on stat card number changes (just swap the value). No skeleton loaders for above-the-fold content that loads instantly. Skeleton only for data that has genuine latency (charts, tables).
Dashboard Variants Catalog
| Type | Stat Cards | Primary Chart | Secondary Content | Demo |
|---|---|---|---|---|
| Classic | Subscriptions, Revenue | Bar + Line | Team members, Chat, Payments table | demo |
| E-commerce | MRR, Users, Growth | Bar (Revenue) | Product list, Returning rate line | demo |
| Sales | Balance, Income, Expense, Tax | Bar (Revenue) | Best selling products, Order table | demo |
| CRM | Customers, Deals, Revenue | Donut (Leads) | Tasks list, Pipeline horizontal bar | demo |
| Project Management | Tasks, Progress, Team | Gantt-style | Task board, Calendar | demo |
| File Manager | Storage used, Files | Usage bar | File grid, Recent files | demo |
| Crypto | Balance, Wallets | Line (Balance) | Wallet cards, Transaction list | demo |
| Academy | Students, Courses | Bar (Enrollment) | Course cards, Schedule | demo |
| Hospital | Patients, Appointments | Line (Admissions) | Doctor schedule, Patient table | demo |
| Analytics | Active users, Sessions, Duration, Conversion | Bar (Earnings) | Donut (completion), Traffic sources | demo |
| Finance | Balance, Profit, Expenses, Invoices | Bar (Monthly expenses) | Income breakdown, Donut (spending), Transactions | demo |
| Payment | Multi-currency balances | Line (Exchange rates) | Transaction list, Currency converter | demo |
SaaS Dashboard Cheatsheet
The six rules. Memorize these.
| Rule | Spec | Why |
|---|---|---|
| Typography | 14px body, -0.2px letter-spacing |
Readable without feeling editorial |
| Sidebar width | 240px, always | Enough for labels, not enough to waste space |
| Table row height | 48px minimum | Scanability - eyes need vertical breathing room |
| Primary action | Top right, never buried | Users look there first; muscle memory from every SaaS app |
| Empty states | Illustration + CTA | "No data" is a dead end; empty states are onboarding |
| Status colors | Green = done, amber = pending, red = action needed | Three states, three colors, zero ambiguity |
Checklist - Before Shipping a Dashboard
- Base font is 14px, not 16px
- Body text uses
-0.2pxletter-spacing - At most 3 font weights used (regular, medium, semibold)
- All numbers use
tabular-nums - Icons are 16px with 1.5px stroke
- Stat cards have: icon + label + hero value + delta + context
- Delta uses green/red only, with direction indicator
- Card gap is 16px uniform
- Card padding is 20-24px
- Card radius is 8px
- Charts use at most 5 colors
- Table rows are 48-52px height
- Sidebar active state has background fill, not just text color
- Primary action is top right, never buried in the page
- Empty states have illustration + CTA, not just "No data"
- Top bar has search with keyboard shortcut hint
- No animations on instant-load content
- Dark mode backgrounds are near-black (#09090b), not gray
- Dark mode cards use the 1px inner shadow (white 2%) + drop shadow (black 25%)
Timeline
- 2026-04-12 | Created from analysis of 12 shadcnuikit.com admin dashboards (Classic, E-commerce, Sales, CRM, Project Management, File Manager, Crypto, Academy, Hospital Management, Website Analytics, Finance, Payment). 24 preview images (light + dark) archived at
wiki/assets/dashboards/. Live screenshots captured via Chrome browser automation. Design cheatsheet principles (14px base, 16px icons, weight discipline) codified from Kevin's direction. Source: shadcnuikit.com, Kevin Liu - 2026-04-12 | Added dark mode card shadow technique (the 1px rule): inner white shadow at 2% + drop black shadow at 25%. Cross-referenced with Interface Micro-Polish. Source: @PixelJanitor, @AliGrids on X, 2026-04-11
- 2026-04-13 | Added SaaS dashboard cheatsheet (6-rule quick reference),
-0.2pxletter-spacing spec, empty states pattern (illustration + CTA), explicit primary action placement rule (top right, never buried). Updated checklist with new items. Source: Kevin Liu - 2026-07-03 | Deep-reviewed the AliGrids/@_heyrico dashboard artifact and attached it as visual evidence for the existing density rules: 14px base text, 16px icons, thin strokes, restrained weights, quiet sidebars, and stat-card hierarchy. Source: X/@AliGrids, 2026-04-12
- 2026-07-04 | Deep-reviewed Tanjim's CloseCRM dashboard artifact and attached it to the existing SaaS dashboard rules. The local image reinforces 240px-class sidebar rhythm, 48px scan rows, top-right primary action, compact stat cards, and empty/state/action placement as dashboard defaults. Source: X/@Tanjim38, 2026-04-12
- 2026-07-04 | Reviewed shadcn's sidebar scale anecdote and codified sidebar as app-shell infrastructure: shared grouping, active states, collapse behavior, badges, focus, and product-area naming must survive reuse across many surfaces. Source: X/@shadcn, 2026-06-20