---
name: Dashboard (Figma)
description: Analytics or ops dashboard for a fixed desktop canvas — dense data surfaces, multi-column layouts, charts and tables with a restrained palette.
triggers:
  - dashboard
  - analytics dashboard
  - admin dashboard
  - ops console
  - metrics view
  - data dashboard
cd:
  mode: dashboard
  platform: figma-desktop-fixed
  scenario: operations
  preview: figma_frames
  fidelity: high
  speaker_notes: false
  animations: false
  featured: true
  design_system:
    requires: true
    sections: [palette, type, spacing, components]
  craft:
    requires:
      - typography
      - typography-hierarchy
      - color
      - anti-ai-slop
      - accessibility-baseline
      - state-coverage
  inputs:
    - audience (operator / executive / analyst)
    - KPIs (3–6 primary metrics)
    - time grain (day / week / month)
    - filter dimensions (segments the user can slice by)
  parameters:
    - canvas (default 1440×900)
    - density (default comfortable; `compact` tightens row heights)
  outputs:
    primary: figma_frames
    capabilities_required:
      - figma_execute
  default_for:
    - dashboard
  example_prompt: "Analytics dashboard for a fleet ops team — 4 KPIs, last-7-day trend charts, vehicle table with status filters"
---

## Start with the question

A dashboard earns its place by answering a small number of very specific questions. Before composing:

1. List the **3–5 questions** this dashboard must answer in one glance ("Are we on track for the monthly target?" "Which vehicles are flagged now?"). Not topics — questions.
2. Each question maps to one primary widget (stat block, sparkline, table, chart). That is the content plan.
3. Everything else is supporting. If a widget doesn't answer one of the listed questions, drop it.

A dashboard that answers 4 questions clearly beats one that surfaces 14 charts.

## Canvas & grid

- Default canvas 1440×900 (responsive dashboards can also target 1920×1080). State the canvas up front.
- 12-column grid, 24px gutter, 32–48px outer margin. Widgets snap to column boundaries.
- Vertical rhythm: 24 between widgets, 16 within a widget group, 8 inside a widget.
- Sidebar: 240–280px (collapsible to 64px for icon-only), fixed-width. Content fills the rest.
- Top bar: 56–64px with page title, global filters, and user menu. Don't stack two bars.

## Widget palette

Prefer **fewer widget types repeated** over a zoo of one-off visualisations. The dashboard grammar:

- **Stat block** — single KPI, headline number, delta vs previous period, tiny inline sparkline. Used for the top-row summary strip (usually 4 stat blocks).
- **Trend chart** — line or area, 1–3 series, no chart junk. Axis labels muted. Hover-state defined but not decorated in the static view.
- **Bar / segmented** — horizontal bars when comparing categories. Truncate long labels with tooltip on hover.
- **Table** — sortable, with header row using `color.muted`, zebra optional (usually no — rely on row height + 1px border). Primary column left, dimensional columns center, action column right.
- **Status pill** — tiny capsule with icon + label, accent colored by status (success / warning / error / neutral). Use the semantic scale, not the full brand palette.

Three or four widget types per screen is plenty.

## Palette discipline

- `color.bg` for the canvas. `color.surface` for every widget card (flat plane — no gradients).
- `color.accent` for: primary button, selected tab, current-line on charts. At most 2–3 visible uses per screen.
- `color.muted` for axis labels, table headers, secondary text.
- **Status colors** (success / warning / error) are semantic and must exist in the DS separately from the brand palette. If the DS only has brand tokens, ask before inventing.
- Chart series that need more than 3 distinct colors: use OKLch lightness steps of the accent hue, or dedicated categorical tokens if the DS provides them. Never reach for a rainbow.

## Typography

- Numbers are the point. Tabular figures on all KPIs and tables. Monospace for raw IDs.
- Headline KPI: 32–40pt bold. Delta below, 12–14pt, color-coded success/error.
- Table body: 13–14pt. Row height 44–52 comfortable, 36–40 compact.
- Never more than 4 type sizes across the entire dashboard.

## State coverage (non-negotiable for data surfaces)

Every widget must handle:

- **Loading** — skeleton shape that matches the final layout (row-shaped lines for tables, rectangle for charts). No full-screen spinners.
- **Empty** — specific copy ("No incidents in the last 24h — that's a good day.") with a faint illustration or icon. Never "No data available."
- **Error** — inline error with a retry affordance. Preserve the widget frame — don't collapse it.
- **Zero / negative value** — charts with no data above zero must still render the axis and a clear "0" baseline.

## Interaction affordances

- Filters live in the top bar or a left-rail panel — never both.
- Time-range selector uses a consistent token: `1d / 7d / 30d / custom`. Apply the same token across widgets.
- Clickable rows: entire row is the target, not just the chevron. Highlight on hover with a `color.surface` variant, not an accent tint.
- Empty filter results: show the applied filters as removable chips above the empty state.

## Anti-patterns

- Doughnut / pie charts with more than 4 slices. Use a horizontal bar.
- Two-stop gradient backgrounds behind KPIs. Flat surface + restrained type is always stronger.
- Status conveyed by color alone — always pair with an icon or label for a11y.
- Stacked bar with 7+ categories — becomes unreadable. Cluster or drop to the top 5 + "other".
- Emoji in headers or status pills.
- A sidebar that both collapses AND has tooltips AND has secondary nav levels — one complication too many.

## Quality bar

Before replying, check that every widget on screen answers one of the listed questions from step 1. If you can delete a widget and none of the questions go unanswered, delete it. Then run `craft_lint` on the concatenated text (headers, labels, empty-state copy).
