dashboard-design
USE THIS SKILL FIRST when user wants to create and design a dashboard, ESPECIALLY Vizro dashboards. This skill enforces a 3-step workflow (requirements, layout, visualization) that must be followed before implementation. For implementation and testing, use the dashboard-build skill after completing Steps 1-3.
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install mckinsey-vizro-dashboard-design
Repository
Skill path: vizro-e2e-flow/skills/dashboard-design
USE THIS SKILL FIRST when user wants to create and design a dashboard, ESPECIALLY Vizro dashboards. This skill enforces a 3-step workflow (requirements, layout, visualization) that must be followed before implementation. For implementation and testing, use the dashboard-build skill after completing Steps 1-3.
Open repositoryBest for
Primary workflow: Design Product.
Technical facets: Full Stack, Designer, Testing.
Target audience: everyone.
License: Unknown.
Original source
Catalog source: SkillHub Club.
Repository owner: mckinsey.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install dashboard-design into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/mckinsey/vizro before adding dashboard-design to shared team environments
- Use dashboard-design for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: dashboard-design
description: USE THIS SKILL FIRST when user wants to create and design a dashboard, ESPECIALLY Vizro dashboards. This skill enforces a 3-step workflow (requirements, layout, visualization) that must be followed before implementation. For implementation and testing, use the dashboard-build skill after completing Steps 1-3.
---
# Building Vizro Dashboards
A structured workflow for creating effective dashboards with Vizro.
## How to Use This Skill
**CRITICAL**: Use this skill BEFORE implementation. After completing Steps 1-3, proceed to the dashboard-build skill for implementation and testing.
**IMPORTANT**: Follow steps sequentially. Each step builds on the previous.
Copy this checklist and track your progress:
```
Dashboard Development Progress:
- [ ] Step 1: Understand Requirements (discuss with user, document decisions)
- [ ] Step 2: Design Layout & Interactions (wireframes, filter placement)
- [ ] Step 3: Select Visualizations (chart types, colors, KPIs)
- [ ] Next: Use dashboard-build skill for implementation and testing
```
**Do not skip steps.** Handle partial context as follows:
- User has data but no requirements → Start at Step 1
- User has wireframes → Validate Step 1 decisions, then proceed from Step 2
- User has visual designs/mockups → Validate Steps 1-2 decisions, then proceed from Step 3
- User asks to "just build it" → Explain value of steps, offer to streamline but not skip
**For simple dashboards** (single page, less than 5 charts): Steps 1-3 can be abbreviated but not skipped entirely.
---
## Spec Files: Documenting Decisions
IMPORTANT: Each step produces a spec file in the `spec/` directory to document reasoning, enable collaboration, and allow resumption in future sessions. Create the `spec/` directory at project start.
---
## Step 1: Understand Requirements
**Goal**: Define WHAT information is presented and WHY it matters.
### Key Questions to Discuss
1. **Users**: Who uses this dashboard? What decisions do they make?
1. **Questions**: What are the 3-5 most important questions this answers?
1. **Data**: What sources are available? What's the refresh frequency?
1. **Structure**: How many pages? What's the logical grouping?
### Design Principles
- **Limit KPIs**: 5-7 primary metrics per page maximum
- **Clear hierarchy**: Overview → Detail → Granular (max 3 levels)
- **Persona-based**: Different users may need different views
- **Decision-focused**: Every metric should inform a decision
### REQUIRED OUTPUT: spec/1_information_architecture.yaml
Save this file BEFORE proceeding to Step 2:
```yaml
# spec/1_information_architecture.yaml
dashboard:
name: [Name]
purpose: [One sentence goal]
pages:
- name: [Page Name]
purpose: [What question does this answer?]
kpis: [List of 3-7 key metrics]
data_sources:
- name: [Source Name]
type: [csv/database/api]
decisions:
- decision: [What was decided]
reasoning: [Why this choice was made]
```
### Validation Checklist
Before proceeding to Step 2:
- [ ] Every page has a clear, distinct purpose
- [ ] KPIs are measurable and actionable
- [ ] Data sources are accessible
- [ ] User has confirmed the structure
**Detailed guidance**: See [information_architecture.md](references/information_architecture.md); **Anti-patterns**: See [common_mistakes.md](references/common_mistakes.md) section "Step 1: Requirements Mistakes"
---
## Step 2: Design Layout & Interactions
**Goal**: Define HOW users navigate and explore data.
### Vizro Navigation Architecture
```
Tier 1: Global Navigation
├── Multi-page sidebar (automatic in Vizro)
└── Page selection
Tier 2: Page-level Controls
└── Filters/Parameters in left collapsible sidebar
Tier 3: Component-level
├── Container-specific filters/parameters
├── Cross-filter, cross-highlight interactions
└── Export actions
```
### Layout Strategy
**Optimal Grid Configuration**:
- Always use `row_min_height="140px"` (at page or container level)
- **12 columns recommended** (not enforced) - flexible due to many divisors (1, 2, 3, 4, 6, 12)
- Control height by giving components **more rows**
**Component Sizing** (based on 12-column grid, height = rows × 140px):
| Component | Columns | Rows | Height |
| ----------- | --------- | ---- | --------- |
| KPI Card | 3 | 1 | 140px |
| Small Chart | 4 | 3 | 420px |
| Large Chart | 6 | 4-5 | 560-700px |
| Table | 12 (full) | 4-6 | 560-840px |
**Exceptions** - size based on content to render:
- Text-heavy Card → treat like a chart (3+ rows)
- Small Table (less than columns) → doesn't need full width
- Button → 1 row is enough
**Layout Rules**:
- Place 2-3 charts per row (side-by-side)
- Full-width ONLY for time-series line charts
- Give charts minimum 3 rows (use `*[[...]] * 3` pattern)
- Use `-1` for intentional empty cells
### Filter Placement & Selectors
```
Filter needed across multiple visualizations?
├─ YES → Page-level (left sidebar)
└─ NO → Container-level (top of the container)
```
**Choose appropriate selectors** - don't default to Dropdown:
| Data Type | Selector | Example |
| ------------- | --------------- | ------------------------ |
| 2-4 options | **RadioItems** | Region (N/S/E/W) |
| 5+ options | Dropdown | Category (many) |
| Numeric range | **RangeSlider** | Price ($0-$1000) |
| Single number | **Slider** | Year (2020-2025) |
| Date | **DatePicker** | Order date |
| Multi-select | **Checklist** | Status (Active, Pending) |
### REQUIRED OUTPUT: spec/2_interaction_ux.yaml
Save this file BEFORE proceeding to Step 3:
```yaml
# spec/2_interaction_ux.yaml
pages:
- name: [Must match Step 1]
layout_type: grid # or flex
grid_columns: 12
grid_pattern: [[0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3]] # Component placement
containers:
- name: [Container Name]
has_own_filters: true/false
filter_placement:
page_level: [columns with selector types]
container_level: [columns with selector types]
wireframe: |
[ASCII wireframe for ALL pages]
decisions:
- decision: [What was decided]
reasoning: [Why this choice was made]
```
### Validation Checklist
Before proceeding to Step 3:
- [ ] Layout follows Vizro constraints
- [ ] Filter placement is intentional and documented
- [ ] User has been presented ASCII wireframes for every page and approved them
**Wireframes & examples**: See [layout_patterns.md](references/layout_patterns.md); **Anti-patterns**: See [common_mistakes.md](references/common_mistakes.md) section "Step 2: Layout Mistakes"
---
## Step 3: Select Visualizations
**Goal**: Choose appropriate chart types and establish visual consistency.
### Chart Type Quick Reference
| Data Question | Recommended Chart |
| ----------------------- | ----------------------------------- |
| Compare categories | Bar chart (horizontal for 8+ items) |
| Show trend over time | Line chart (12+ points) |
| Part-to-whole (simple) | Pie/donut (2-5 slices ONLY) |
| Part-to-whole (complex) | Stacked bar chart |
| Distribution | Histogram or box plot |
| Correlation | Scatter plot |
### Chart Anti-Patterns (Never Use)
- 3D charts, Pie charts with 6+ slices, Dual Y-axis, Bar charts not starting at zero
### Color Strategy
**Primary Rule**: Let Vizro handle colors automatically for standard charts.
**When to specify colors**:
- Semantic meaning (green=good, red=bad)
- Consistent entity coloring across charts
- Brand requirements
**Vizro Semantic Colors**:
```python
success_color = "#689f38" # Green - positive
warning_color = "#ff9222" # Orange - caution
error_color = "#ff5267" # Pink/red - negative
neutral_color = "gray" # Inactive
```
### KPI Card Pattern
Use `kpi_card()` for simple metrics, `kpi_card_reference()` for comparisons. Use `reverse_color=True` when lower is better (costs, errors). NEVER put `kpi_card` or `kpi_card_reference` as a custom chart or re-build KPI cards as custom charts, use the built-in `kpi_card` and `kpi_card_reference` in `Figure` model instead. Only accept exceptions for when the KPI card is strictly not possible, for example when dynamically showing text as a KPI card.
### Chart Title Pattern
**IMPORTANT**: Titles go in `vm.Graph(title=...)`, NOT in plotly code.
### REQUIRED OUTPUT: spec/3_visual_design.yaml
Save this file BEFORE proceeding to implementation (dashboard-build skill):
```yaml
# spec/3_visual_design.yaml
visualizations:
- name: [Chart Name]
type: [bar/line/scatter/etc]
needs_custom_implementation: true/false
reason: [if custom: has_reference_line/needs_data_processing/etc]
color_decisions:
- component: [Name]
reason: [Why non-default color]
colors: [List of hex codes]
kpi_cards:
- name: [KPI Name]
value_column: [column]
format: [e.g., '${value:,.0f}']
has_reference: true/false
decisions:
- decision: [What was decided]
reasoning: [Why this choice was made]
```
### Validation Checklist
Before proceeding to implementation (dashboard-build skill):
- [ ] Chart types match data types (no pie charts for time series)
- [ ] No anti-patterns used
- [ ] Custom chart needs are identified
- [ ] Color usage is consistent and intentional
**Chart decision trees**: See [chart_selection.md](references/chart_selection.md); **Anti-patterns**: See [common_mistakes.md](references/common_mistakes.md) section "Step 3: Visualization Mistakes"
## Reference Files
| File | When to Read |
| --------------------------------------------------------------------- | ------------------------------------ |
| [information_architecture.md](references/information_architecture.md) | Step 1: Deep dive on requirements |
| [layout_patterns.md](references/layout_patterns.md) | Step 2: Wireframes, component sizing |
| [chart_selection.md](references/chart_selection.md) | Step 3: Chart decision trees |
| [common_mistakes.md](references/common_mistakes.md) | All steps: Anti-patterns to avoid |
---
## Quick Reference: Vizro Components
**Components**: `Dashboard`, `Page`, `Container`, `Tabs`, `Graph`, `Figure`, `AgGrid`, `Card`, `Filter`, `Parameter`, `Selector`, `Button`
**Key Imports**: `import vizro.models as vm`, `from vizro import Vizro`, `import vizro.plotly.express as px`, `from vizro.tables import dash_ag_grid`, `from vizro.figures import kpi_card, kpi_card_reference`, `from vizro.models.types import capture`
---
## Referenced Files
> The following files are referenced in this skill and included for context.
### references/information_architecture.md
```markdown
# Information Architecture Guide
Deep guidance for Step 1: Understanding Requirements.
## Contents
- The Foundation of Effective Dashboards
- Requirements Gathering Framework (business context, analytical questions, data sources, KPIs, page structure)
- Common Mistakes in Information Architecture
- Validation Framework (checklist)
- Example: E-Commerce Dashboard IA
## The Foundation of Effective Dashboards
Information architecture determines dashboard success more than visual design. A beautiful dashboard with wrong metrics fails; an ugly dashboard with right metrics succeeds.
## Requirements Gathering Framework
### 1. Understand the Business Context
**Questions to ask**:
- What business process does this dashboard support?
- What decisions will users make based on this data?
- What happens if these decisions are wrong or delayed?
- Who are the primary users? Secondary users?
**User Archetypes**:
| Type | Needs | Dashboard Approach |
| --------- | ----------------------------- | ---------------------------- |
| Executive | High-level trends, exceptions | KPIs, sparklines, alerts |
| Manager | Team performance, comparisons | Comparisons, drill-downs |
| Analyst | Deep exploration, raw data | Filters, tables, exports |
| Operator | Real-time status, actions | Live metrics, action buttons |
### 2. Define Analytical Questions
Every page should answer specific questions. Document them explicitly:
**Good questions** (actionable):
- "Which regions are underperforming this quarter?"
- "Are we on track to meet the monthly target?"
- "Which products should we restock?"
**Bad questions** (too vague):
- "What's happening with sales?"
- "Show me everything about customers"
- "Give me all the data"
### 3. Inventory Data Sources
| Source | Type | Refresh | Owner | Quality |
| ------------- | ---------- | --------- | ----------- | ------- |
| sales_db | PostgreSQL | Daily | Data Team | High |
| marketing.csv | File | Weekly | Marketing | Medium |
| api/metrics | REST API | Real-time | Engineering | High |
**Data quality considerations**:
- Missing values: How to handle?
- Data freshness: Is delayed data acceptable?
- Access permissions: Who can see what?
### 4. Select KPIs
**The 5-7 Rule**: No more than 5-7 primary KPIs per page.
**KPI Selection Criteria**:
- **Measurable**: Can be quantified precisely
- **Actionable**: User can do something about it
- **Timely**: Available when needed
- **Relevant**: Directly tied to business goals
**KPI Hierarchy**:
```
Primary KPIs (3-5): Featured prominently, answer main questions
├── Supporting metrics: Provide context for primary KPIs
└── Detail metrics: Available on drill-down
```
**Example: Sales Dashboard**
```
Primary KPIs:
- Total Revenue (vs target)
- Conversion Rate
- Average Order Value
- Customer Acquisition Cost
Supporting:
- Revenue by Region
- Top Products
- Sales Pipeline
Detail (drill-down):
- Individual transactions
- Customer details
```
### 5. Design Page Structure
**Organizational Patterns**:
| Pattern | Best For | Example |
| ---------- | -------------------- | ----------------------------------- |
| By Role | Different user needs | Executive / Manager / Analyst views |
| By Topic | Domain areas | Sales / Marketing / Operations |
| By Process | Workflow stages | Lead → Opportunity → Close |
| By Time | Temporal analysis | Daily / Weekly / Monthly |
**Information Flow**:
```
Level 1: Overview (3-7 primary KPIs, high-level trends)
├── High-level KPIs
├── Trend summaries
└── Exception alerts
Level 2: Analysis (supporting metrics, comparative data via tabs/sections)
├── Comparisons
├── Breakdowns
└── Filters
Level 3: Detail (individual records, deep analysis via drill-downs)
├── Individual transactions
├── Raw data tables
└── Export capability
```
**Drill-Down Patterns**:
- Click on chart → Filtered detail view
- Hover → Tooltip with exact values
- Click on metric → Time series or breakdown
- "Show more" → Expanded table or list
**Data Density Management**:
| User Type | Data Density | Approach |
| --------- | ------------ | ----------------------------------- |
| Executive | Low | KPIs, sparklines, exceptions only |
| Manager | Medium | Comparisons, summaries, key filters |
| Analyst | High | Full exploration, raw data, exports |
| Operator | Medium-High | Real-time metrics, action buttons |
**Page Limit Guidelines**:
- 1-3 pages: Simple operational dashboard
- 4-7 pages: Comprehensive business dashboard
- 8+ pages: Consider splitting into multiple dashboards
## Common Mistakes in Information Architecture
### 1. Everything on One Page
**Problem**: 20+ metrics crammed together **Solution**: Prioritize ruthlessly, use drill-downs
### 2. No Clear Hierarchy
**Problem**: All metrics appear equally important **Solution**: Define primary vs supporting vs detail metrics
### 3. Data-Driven Instead of Question-Driven
**Problem**: "We have this data, let's show it" **Solution**: Start with questions users need answered
### 4. Ignoring User Context
**Problem**: Same dashboard for executives and analysts **Solution**: Role-specific views or pages
### 5. Missing Comparisons
**Problem**: Numbers without context (Revenue: $1.2M... is that good?) **Solution**: Always include comparison (vs target, vs last period, vs benchmark)
## Validation Framework
Before moving to Step 2, verify:
```
Information Architecture Checklist:
- [ ] Dashboard purpose is clear in one sentence
- [ ] Target users are identified
- [ ] Each page answers specific questions (documented)
- [ ] Primary KPIs are limited (5-7 per page)
- [ ] Data sources are accessible and understood
- [ ] Information hierarchy is defined (primary/supporting/detail)
- [ ] User has explicitly confirmed the structure
```
## Example: E-Commerce Dashboard IA
```yaml
dashboard:
name: E-Commerce Performance
purpose: Monitor sales performance and identify growth opportunities
users: [Sales Manager, Marketing Director]
pages:
- name: Executive Summary
purpose: Are we hitting targets? What needs attention?
kpis:
- Total Revenue (vs target)
- Orders This Month
- Conversion Rate
- Customer Acquisition Cost
supporting:
- Revenue trend (sparkline)
- Top performing category
- name: Sales Analysis
purpose: Where are sales coming from? What's trending?
kpis:
- Revenue by Region
- Revenue by Category
- Sales Pipeline Value
interactions:
- Filter by date range
- Filter by region
- Drill to product detail
- name: Customer Insights
purpose: Who are our customers? How do we retain them?
kpis:
- New vs Returning Customers
- Customer Lifetime Value
- Churn Rate
interactions:
- Filter by segment
- Drill to customer detail
data_sources:
- name: orders_db
type: PostgreSQL
refresh: Hourly
tables: [orders, order_items, customers]
- name: marketing_metrics
type: API
refresh: Daily
metrics: [ad_spend, impressions, clicks]
```
```
### references/common_mistakes.md
```markdown
# Common Dashboard Mistakes
Anti-patterns to avoid, organized by dashboard development step.
## Contents
- Step 1: Requirements Mistakes (information overload, ignoring user workflow)
- Step 2: Layout Mistakes (poor hierarchy, cluttered layout)
- Step 3: Visualization Mistakes (wrong charts, color misuse, missing context)
- Quick Fixes Reference
---
## Step 1: Requirements Mistakes
Mistakes in defining WHAT information to show and WHY.
### Information Overload
**Problem**:
- Too many metrics on single screen (>12 charts)
- Every available metric included
- No clear focus or priority
- Users cannot identify what matters
**Solution**:
- Follow "7 ± 2 rule": 5-9 key metrics maximum on main view
- Prioritize based on user goals
- Grouping related metrics into sections
- Create role-specific views
- Ask: "Does this help make a decision?"
### Ignoring User Workflow
**Problem**:
- Dashboard doesn't match user tasks
- Wrong metrics for user role
- No filtering options
- One-size-fits-all approach
**Solution**:
- Start with Step 1 requirements gathering
- Create role-specific pages
- Allow filtering and customization
- Match metrics to decisions users make
### Non-Actionable Metrics
**Problem**: Metrics displayed but no action possible
**Solution**: Only show metrics that inform decisions; consider removing vanity metrics
### The "Hidden Value"
**Problem**: Most important info requires multiple clicks
**Solution**: Surface critical insights immediately on overview page
### The "Metric Graveyard"
**Problem**: Metrics no one looks at anymore
**Solution**: Regular audits; remove unused metrics
---
## Step 2: Layout Mistakes
Mistakes in HOW users navigate and explore data.
### Poor Visual Hierarchy
**Problem**:
- All elements same size and weight
- Important metrics buried
- Random placement without logic
- No clear scanning path
**Solution**:
- Place critical KPIs top-left (F-pattern)
- Use size to indicate importance
- Group related metrics visually
- Create clear sections with spacing
**Visual Weight Guide**:
```
Primary metric: Large KPI card, prominent position
Secondary metric: Medium chart, supporting position
Tertiary metric: Smaller chart or table row
```
### Cluttered Layout
**Problem**:
- No white space
- Charts touching each other
- Dense, cramped feeling
- Difficult to distinguish sections
**Solution**:
- Use Grid layout with proper spacing
- Use containers to group related items
- Set appropriate `row_min_height`
- Leave visual breathing room
**Spacing Guidelines**:
```python
# Good: Charts span 3 rows (420px each)
vm.Grid(
grid=[
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1],
],
row_min_height="140px",
)
# Bad: Charts only 1 row (140px - too small)
vm.Grid(grid=[[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1]], row_min_height="140px")
```
### Inconsistent Time Ranges
**Problem**: Different charts showing different time periods
**Solution**: Use page-level date filter that affects all charts
### The "Surprise Me" Dashboard
**Problem**: Random order, no predictable structure
**Solution**: Consistent layout users can learn and memorize
---
## Step 3: Visualization Mistakes
Mistakes in chart types, colors, and visual design.
### Inappropriate Chart Types
**Problem Examples**:
- Pie chart with 10+ slices
- Pie chart for time-series data
- 3D charts distorting values
- Line chart for categorical comparison
- Bar chart without zero baseline
**Solutions**:
| Wrong | Right | Why |
| ---------------- | --------------------- | ------------------- |
| Pie (10 slices) | Horizontal bar | Readable |
| Time-series pie | Line/area chart | Shows trend |
| 3D bar chart | 2D bar chart | Accurate perception |
| Categorical line | Bar chart | No false continuity |
| Truncated bars | Zero baseline or line | Not misleading |
### Color Misuse
**Problem**:
- Too many colors (>6)
- Similar shades hard to distinguish
- Inconsistent color meanings
- "Christmas tree" effect
**Solution**:
- Limit to 3 primary colors + neutrals
- Use color consistently (same entity = same color everywhere)
- Let Vizro handle colors automatically for most charts
- Reserve bright colors for highlights only
**Color Budget**:
```
Primary data: 1 color
Comparison: 1 contrasting color
Highlights/alerts: 1 accent color
Everything else: Grayscale
```
### Lack of Context
**Problem**:
- Numbers without comparison
- No date ranges shown
- Missing units or labels
- Unclear what "good" means
**Solution**:
- Always include comparisons (vs target, vs last period)
- Show date range prominently
- Include units in labels (%, $, units)
- Add reference lines for targets
- Show trends (up/down indicators)
**Context Template**:
```
[Metric Name]: [Value] [Unit]
[Time Period]
[Comparison]: [Direction] [Amount] vs [Reference]
Example: Revenue: $1.2M | Oct 2024 | +15% vs last month
```
### Inconsistent Design
**Problem**:
- Different chart styles across dashboard
- Varying font sizes and styles
- Inconsistent colors for same data
- Mixed labeling conventions
**Solution**:
- Use Vizro defaults (automatic consistency)
- Same color for same entity everywhere
- Consistent title format across charts
- Uniform tooltip format
### Truncated Y-Axis on Bar Charts
**Problem**: Bar charts not starting at zero exaggerate differences
**Solution**: Always start bar charts at zero; use line charts if truncation needed
### Too Many Decimal Places
**Problem**: `$1,234,567.89` or `45.3478%` creates cognitive load
**Solution**: Round appropriately
```python
# Good
value_format = "${value:,.0f}" # $1,234,568
value_format = "{value:.1f}%" # 45.3%
# Bad
value_format = "${value:,.2f}" # $1,234,567.89
```
### Unclear Metric Names
**Problem**: "Conv Rate" or "ARPU" without explanation
**Solution**: Use full names or include header/footer for context
```python
vm.Graph(
figure=px.bar(...),
title="Conversion Rate",
header="Percentage of visitors who made a purchase",
)
```
### Missing Legends
**Problem**: Colors without legend
**Solution**: Plotly includes legends by default; ensure they're visible
### Hidden Insights
**Problem**: Important findings buried in data
**Solution**: Surface key insights in KPI cards or chart titles
### The "Decorative Dashboard"
**Problem**: Pretty but not functional
**Solution**: Form follows function; beauty through clarity
### Custom charts as KPI cards
**Problem**: Model uses custom charts as KPI cards. This often happens when the model needs to do some additional data manipulation that cannot be done with the built-in Vizro functions.
**Solution**: Custom charts are not KPI cards. Instead, the model should use the built-in Vizro functions (`kpi_card` or `kpi_card_reference`) and do data manipulation in the data loading/processing step. The only acceptable exception is when the KPI card is strictly not possible, for example when dynamically showing text as a KPI card.
```
### references/layout_patterns.md
```markdown
# Layout Patterns Guide
Deep guidance for Step 2: Designing Layout & Interactions.
## Contents
- Layout System Overview
- Component Sizing Guidelines
- Wireframe Templates
- Container Patterns
- Filter and Parameter Placement
- Visual Hierarchy Principles
- Common Layout Mistakes
- Vizro-Specific Constraints
## Layout System Overview
Vizro provides two layout options:
- **Grid**: Precise control over component placement and sizing (recommended)
- **Flex**: Automatic vertical stacking with spacing (simple pages only)
**Recommendation**: Use Grid for most dashboards. Use Flex only for very simple single-column pages.
### Grid Concept
The grid divides page width into columns. Components are placed by specifying which columns they occupy. Height is controlled by how many **rows** a component spans.
**Key principles**:
- **12 columns recommended** (not enforced) - provides flexibility with many divisors (1, 2, 3, 4, 6, 12)
- Any column count works if there's good reason (e.g., 8 columns for simpler layouts)
- Control height by giving components more rows
- Each row is 140px tall (use `row_min_height="140px"`)
- Component height = rows × 140px
**Note**: All examples in this guide use 12 columns as a comprehensive default, but adapt as needed.
## Component Sizing Guidelines
Based on 12-column grid:
| Component | Columns | Rows | Min Height |
| ----------- | --------- | ---- | ---------- |
| KPI Card | 3 | 1 | 140px |
| Small Chart | 4 | 3 | 420px |
| Large Chart | 6 | 4-5 | 560-700px |
| Table | 12 (full) | 4-6 | 560-840px |
**Exceptions** - size based on content to render:
- Text-heavy Card → treat like a chart (3+ rows)
- Small Table (less than 5 columns) → doesn't need full width
- Button → 1 row is enough
**Flexible Width Distributions** (12-column advantage):
12 columns allows uneven widths since 12 has many divisors (1, 2, 3, 4, 6, 12):
| Layout | Column Distribution |
| ---------------------- | ------------------- |
| 3 equal charts | 4 + 4 + 4 |
| Primary + 2 secondary | 6 + 3 + 3 |
| Two-thirds + one-third | 8 + 4 |
| Two equal charts | 6 + 6 |
| 4 KPI cards | 3 + 3 + 3 + 3 |
## Wireframe Templates
### Component Labels for Wireframes
| Label | Description |
| ------------- | ---------------------------------------------------------------------- |
| **KPI** | Metric cards |
| **CHART** | Visualizations with type: `[Line chart]`, `[Bar chart]`, `[Histogram]` |
| **TABLE** | Data tables with features: `[sortable]`, `[pagination]` |
| **CONTAINER** | Groups components, can have own filters/parameters |
| **TABS** | Multiple views with tab labels |
| **FILTER** | In left panel (global) or above container (scoped) |
| **PARAMETER** | In left panel (global) or above container (scoped) |
| **ACTIONS** | Buttons for export, drill-down, etc. |
### Interaction Annotations
- `[↗ click: drill-down]` - Clicking navigates to detail
- `[hover: tooltip]` - Hovering shows information
- `[↗ click: toggle series]` - Clicking toggles chart elements
- `[sortable columns]` - Interactive table sorting
### Wireframing Guidelines
1. Use three-column layout: icon nav | left panel | main content
1. Label sections: KPI, CHART, TABLE, FILTER, PARAMETER, CONTAINER, TABS
1. Indicate chart types: `[Line chart]`, `[Bar chart]`, `[Histogram]`
1. Show hierarchy through box sizes (larger = more important)
1. Global filters/parameters in left panel, container-specific above containers
1. **Full-width charts**: Use ONLY for time-series line charts
1. Most charts should be side-by-side (2-3 per row)
### Template 1: KPIs + Charts + Table
```
+--+----------+------------------------------------------------------------------------+
| |NAV | |
| | +------------------------------------------------------------------------+
| |Page 1 | +-------------+ +-------------+ +-------------+ +-------------+ |
| |Page 2 | | KPI 1 | | KPI 2 | | KPI 3 | | KPI 4 | |
| |Page 3 | | (3 cols) | | (3 cols) | | (3 cols) | | (3 cols) | |
| | | +-------------+ +-------------+ +-------------+ +-------------+ |
| |----------| |
| |FILTERS | +----------------------------------+ +-----------------------------+ |
| | | | | | | |
| |Date | | CHART: Primary Visualization | | CHART: Secondary | |
| |[v] | | [Bar chart] | | [Line chart] | |
| | | | (6 cols, 3 rows) | | (6 cols, 3 rows) | |
| |Region | +----------------------------------+ +-----------------------------+ |
| |[v] | |
| | | +---------------------------------------------------------------------+|
| |Category | | ||
| |[v] | | TABLE: Detail Data (12 cols, 2 rows) ||
| | | | [sortable, filterable] ||
| | | +---------------------------------------------------------------------+|
+--+----------+------------------------------------------------------------------------+
```
### Template 2: Full-Width Time-series + Container
```
+--+----------+------------------------------------------------------------------------+
| |NAV | |
| | +------------------------------------------------------------------------+
| |Overview | +---------------------------------------------------------------------+|
| |Details | | ||
| | | | CHART: Revenue Trend [Time-series Line - Full Width] ||
| |----------| | (12 cols, 3 rows) ||
| |FILTERS | | [hover: tooltip | click: drill to detail] ||
| | | +---------------------------------------------------------------------+|
| |Year | |
| |[v] | CONTAINER: Regional Breakdown (12 cols, 3 rows) |
| | | [Container Filter: Region v] |
| |Quarter | +------------------+ +------------------+ +------------------------+|
| |[v] | | | | | | ||
| | | | CHART: By Region| | CHART: By Product| | TABLE: Top Items ||
| | | | [Bar chart] | | [Pie chart] | | [sortable] ||
| | | | (4 cols) | | (4 cols) | | (4 cols) ||
| | | +------------------+ +------------------+ +------------------------+|
+--+----------+------------------------------------------------------------------------+
```
### Template 3: Tabs for Multiple Views
```
+--+----------+------------------------------------------------------------------------+
| |NAV | |
| | +------------------------------------------------------------------------+
| |Dashboard | TABS: [Overview] [By Region] [By Product] [Export] |
| | | +---------------------------------------------------------------------+|
| |----------| | TAB CONTENT: Overview ||
| |FILTERS | | ||
| | | | +-------------+ +-------------+ +-------------+ ||
| |Date | | | KPI 1 | | KPI 2 | | KPI 3 | ||
| |[v] | | +-------------+ +-------------+ +-------------+ ||
| | | | ||
| | | | +----------------------------------+ +---------------------------+||
| | | | | CHART: Main Metric | | CHART: Trend |||
| | | | +----------------------------------+ +---------------------------+||
| | | +---------------------------------------------------------------------+|
+--+----------+------------------------------------------------------------------------+
```
## Container Patterns
### When to Use Containers
| Scenario | Use Container? |
| ------------------------- | -------------- |
| Group related charts | Yes |
| Section needs own filters | Yes |
| Visual separation needed | Yes |
| Simple sequential layout | No |
### Container Styling Options
| Style | Use Case |
| -------- | ------------------------------- |
| Plain | No visual styling (default) |
| Filled | Background fill for emphasis |
| Outlined | Border outline (major sections) |
## Filter and Parameter Placement
### Decision Tree
```
Is this filter needed across multiple visualizations?
├─ YES → Page-level filter (left sidebar)
└─ NO → Container-level filter (above container in main area)
```
**Page-level filters**: Always in left collapsible sidebar **Container filters**: Above the container they control
### Filter Selector Selection
**IMPORTANT**: Choose the appropriate selector type based on the data - don't default to Dropdown for everything.
| Data Type | Selector | When to Use |
| -------------- | --------------- | ---------------------------------------- |
| 2-3 options | **RadioItems** | Few mutually exclusive choices |
| 4-7 options | Dropdown | Moderate number of options |
| 8+ options | Dropdown | Many options (with search) |
| Yes/No, On/Off | **Checklist** | Boolean or toggle selections |
| Numeric range | **RangeSlider** | Price, quantity, score ranges |
| Single number | **Slider** | Threshold, limit, single value selection |
| Date | **DatePicker** | Single date or date range selection |
**Examples**:
- Region filter (North, South, East, West) → **RadioItems** (4 options, mutually exclusive)
- Category filter (10+ categories) → Dropdown
- Price range ($0-$1000) → **RangeSlider**
- Year filter (2020-2025) → **Slider** or **DatePicker**
- Active/Inactive status → **RadioItems** or **Checklist**
## Visual Hierarchy Principles
### F-Pattern Priority
Users scan in an F-shape: left to right, then down the left side.
```
+------------------+------------------+
| MOST IMPORTANT | SECOND |
| (top-left) | (top-right) |
+------------------+------------------+
| THIRD | FOURTH |
| (middle-left) | (middle-right) |
+------------------+------------------+
| SUPPORTING | LEAST IMPORTANT |
| (bottom-left) | (bottom-right) |
+------------------+------------------+
```
### Z-Pattern for Scanning
For sparse layouts with few elements, users scan in a Z-shape:
- Place critical KPIs top-left (natural eye starting point)
- Secondary metrics top-right
- Supporting details below
- Least important information bottom-right
### Size Indicates Importance
- **Primary metrics**: Larger cells (6 columns, half width)
- **Secondary metrics**: Medium cells (4 columns, one-third)
- **Supporting details**: Smaller cells (3 columns, quarter width)
## Common Layout Mistakes
### 1. Charts Too Small
**Problem**: Charts crammed into small spaces **Solution**: Minimum 4 columns × 3 rows for any chart
### 2. Everything Full-Width
**Problem**: Every chart spans all columns **Solution**: Only time-series line charts should be full-width
### 3. No Visual Grouping
**Problem**: 10 charts with no clear sections **Solution**: Use containers to group related content
### 4. Filters in Main Area
**Problem**: Filters placed among charts **Solution**: Page filters in left sidebar; container filters above container
## Vizro-Specific Constraints
1. **Page Navigation**: Automatic sidebar (built-in, not customizable)
1. **Page Filters/Parameters**: MUST be in collapsible left sidebar
1. **Layouts**: Use Grid or Flex only (no absolute positioning)
1. **Components**: Limited to `Graph`, `AgGrid`, `Card`, `Figure`
1. **Containers**: Can use `Tabs` for organizing content
1. **Actions**: Export, filter, and parameter actions only
**Important**: Do not use emojis in dashboard implementations.
## Reference
- **Layouts**: https://vizro.readthedocs.io/en/latest/pages/user-guides/layouts/
- **Containers**: https://vizro.readthedocs.io/en/stable/pages/user-guides/container/
```
### references/chart_selection.md
```markdown
# Chart Selection Guide
Deep guidance for Step 3: Selecting appropriate visualizations.
## Contents
- Chart Type Decision Tree (what are you showing?)
- COMPARISON Charts (bar, grouped bar)
- TREND Charts (line, area, column)
- COMPOSITION Charts (pie, stacked bar, stacked area)
- DISTRIBUTION Charts (histogram, box, violin)
- RELATIONSHIP Charts (scatter, bubble)
- PERFORMANCE Charts (bullet, waterfall)
- Specialized Charts (heatmap, treemap)
- Custom Charts (when and why to use custom charts)
- Color Strategy (Vizro palette, semantic colors, accessibility)
- Anti-Patterns to Avoid
- Quick Reference Table
## Chart Type Decision Tree
### 1. What Are You Showing?
```
What is your primary goal?
├── Comparing values → Go to COMPARISON
├── Showing change over time → Go to TREND
├── Showing parts of a whole → Go to COMPOSITION
├── Showing distribution → Go to DISTRIBUTION
├── Showing relationship → Go to RELATIONSHIP
└── Showing performance → Go to PERFORMANCE
```
## COMPARISON Charts
### Bar Chart (Horizontal/Vertical)
**Use for**: Comparing discrete categories or values
**Best when**:
- 3-15 categories
- Significant differences between values
- Category labels are short (vertical) or long (horizontal)
**Avoid when**:
- Categories exceed 15 (consider grouping)
- Time-series data (use line chart)
**Requirements**: Always start Y-axis at zero
```python
# Vertical bar (short labels)
px.bar(df, x="category", y="value")
# Horizontal bar (long labels or many categories)
px.bar(df, x="value", y="category", orientation="h")
```
### Grouped Bar Chart
**Use for**: Comparing subcategories within main categories
**Best when**:
- 2-4 subcategories per group
- Need to compare across groups
**Avoid when**:
- More than 5 subcategories (too cluttered)
- Values are very similar (hard to distinguish)
```python
px.bar(df, x="category", y="value", color="subcategory", barmode="group")
```
## TREND Charts
### Line Chart
**Use for**: Showing trends over continuous time
**Best when**:
- 12+ data points
- Continuous time series
- Comparing 2-5 series
**Avoid when**:
- Comparing distinct categories (use bar)
- Non-sequential data
**Best practices**:
- Limit to 3-5 lines maximum
- Use distinct colors
- Full-width layout recommended for time-series
```python
px.line(df, x="date", y="revenue", color="region")
```
### Area Chart
**Use for**: Showing cumulative trends, volume over time
**Best when**:
- Emphasizing magnitude of change
- Single series or stacked comparison
**Avoid when**:
- Multiple overlapping series (use stacked area or line)
```python
# Single series
px.area(df, x="date", y="volume")
# Stacked (composition over time)
px.area(df, x="date", y="value", color="category")
```
### Column Chart
**Use for**: Comparing values across discrete time periods
**Best when**:
- Fewer than 12 time periods
- Showing discrete intervals (Q1, Q2, etc.)
**Avoid when**:
- Continuous time with many points (use line)
```python
px.bar(df, x="quarter", y="revenue")
```
## COMPOSITION Charts
### Pie Chart / Donut Chart
**Use for**: Showing proportions of a whole
**Best when**:
- 2-5 categories ONLY
- One category is notably larger (>25%)
- Showing simple percentage breakdown
**Avoid when**:
- More than 5 categories
- Similar-sized slices
- Comparing multiple pies
**Warning**: Pie charts are often misused. Consider bar chart alternative.
```python
# Pie (2-5 categories only!)
px.pie(df, values="amount", names="category")
# Donut (shows total in center)
px.pie(df, values="amount", names="category", hole=0.4)
```
### Stacked Bar Chart
**Use for**: Comparing composition across multiple groups
**Best when**:
- Comparing how parts make up wholes across categories
- 2-5 segments per bar
```python
# Absolute values
px.bar(df, x="region", y="sales", color="product", barmode="stack")
# Percentages (100% stacked)
px.bar(df, x="region", y="sales", color="product", barmode="stack", barnorm="percent")
```
### Stacked Area Chart
**Use for**: Showing composition over time
**Best when**:
- Need to show both trend and composition
- 2-5 categories
```python
px.area(df, x="date", y="value", color="category")
```
## DISTRIBUTION Charts
### Histogram
**Use for**: Showing frequency distribution of continuous data
**Best when**:
- Large datasets (50+ values)
- Understanding data spread
**Avoid when**:
- Categorical data
- Small sample sizes (less than 30)
```python
px.histogram(df, x="value", nbins=20)
```
### Box Plot
**Use for**: Showing statistical distribution (quartiles, outliers)
**Best when**:
- Comparing distributions across groups
- Technical/analytical audience
**Avoid when**:
- Audience unfamiliar with box plots
- Need to show actual data points
```python
px.box(df, x="category", y="value")
```
### Violin Plot
**Use for**: Showing distribution shape with density
**Best when**:
- Need more detail than box plot
- Comparing distribution shapes
```python
px.violin(df, x="category", y="value")
```
## RELATIONSHIP Charts
### Scatter Plot
**Use for**: Showing correlation between two variables
**Best when**:
- Looking for patterns, relationships, clusters
- Two continuous variables
**Avoid when**:
- No relationship exists
- Too many overlapping points (use density plot)
```python
px.scatter(df, x="price", y="sales", color="category", size="quantity")
```
### Bubble Chart
**Use for**: Scatter with third variable encoded as size
**Use with caution**:
- Size differences hard to judge accurately
- Overlapping bubbles problematic
```python
px.scatter(df, x="x", y="y", size="z", color="category")
```
## PERFORMANCE Charts
### Bullet Chart
**Use for**: Showing performance against targets
**Best when**:
- Comparing actual vs target
- Including context ranges (poor/good/excellent)
```python
# Requires custom implementation with @capture("graph")
```
### Waterfall Chart
**Use for**: Showing cumulative effect of sequential values
**Best when**:
- Explaining how starting value becomes final value
- Financial breakdowns (revenue → costs → profit)
```python
import plotly.graph_objects as go
# Requires go.Waterfall for full control
```
## Specialized Charts
### Heatmap
**Use for**: Showing intensity across two dimensions
**Best when**:
- Large datasets
- Pattern recognition
- Correlation matrices
```python
px.density_heatmap(df, x="day", y="hour", z="value")
```
### Treemap
**Use for**: Hierarchical part-to-whole relationships
**Best when**:
- Nested categories
- Many categories (where pie fails)
```python
px.treemap(df, path=["region", "country", "city"], values="sales")
```
## Custom Charts
Standard `plotly.express` charts cover basic needs, but custom charts unlock more sophisticated visualizations that can tell a better story.
### When to Use Custom Charts
Use the `@capture("graph")` decorator when you need:
- **Post-update calls**: `update_layout()`, `update_xaxes()`, `update_traces()` to customize appearance
- **Reference lines or annotations**: Target lines, thresholds, trend lines
- **Data manipulation**: Calculations or transformations before visualization
- **Advanced chart types**: Waterfall, bullet charts, or multi-trace `go.Figure()` compositions
- **Custom styling**: Specific formatting not available in `px` defaults
### What Custom Charts Enable
Custom charts are powerful. They let you:
- Add horizontal/vertical reference lines showing targets or benchmarks
- Create multi-layered visualizations combining different trace types
- Apply conditional formatting based on data values
- Build chart types not available in `plotly.express`
- Customize every aspect of the visualization
## Color Strategy
### Default Approach: Let Vizro Handle Colors
**Primary rule**: For standard charts, do NOT specify colors. Vizro automatically applies colorblind-accessible palettes.
### Vizro Core Color Palette
When colors must be specified (semantic meaning, brand, consistency):
```python
vizro_colors = [
"#00b4ff", # Bright blue
"#ff9222", # Orange
"#3949ab", # Deep blue
"#ff5267", # Pink/red
"#08bdba", # Teal
"#fdc935", # Yellow
"#689f38", # Green
"#976fd1", # Purple
"#f781bf", # Light pink
"#52733e", # Olive
]
```
### Semantic Color Usage
| Meaning | Color | Hex Code |
| ----------------- | -------- | --------- |
| Positive/Success | Green | `#689f38` |
| Warning/Caution | Orange | `#ff9222` |
| Error/Negative | Pink/Red | `#ff5267` |
| Neutral/Info | Blue | `#00b4ff` |
| Inactive/Disabled | Gray | `gray` |
### Color Palette Rules
**3-Color Maximum**:
- Primary: One Vizro core color
- Secondary: Complementary from core colors
- Accent: For emphasis
- Neutral: Gray for backgrounds/borders
**Sequential Scales** (continuous data):
- Light to dark single hue
- Derive from one Vizro core color
- 3-7 steps with sufficient contrast
**Diverging Scales** (data with midpoint):
- Two colors meeting at neutral
- Example: `#ff5267` (negative) ← gray → `#689f38` (positive)
### Color Accessibility
**Contrast Requirements**:
- Text on background: Minimum 4.5:1 (WCAG AA)
- Large text (18px+): Minimum 3:1
- Chart elements: Minimum 3:1 against background
**Color Blindness**:
- Never use color alone to convey information
- Supplement with patterns, icons, or labels
- Vizro default palettes are colorblind-safe
## Anti-Patterns to Avoid
### Never Use
| Chart Type | Problem | Alternative |
| --------------- | ----------------------- | --------------- |
| 3D Charts | Distort perception | 2D equivalent |
| Dual Y-Axis | Confusing, manipulative | Separate charts |
| Pie (6+ slices) | Unreadable | Bar chart |
| Radar/Spider | Hard to interpret | Small multiples |
### Use with Caution
| Chart Type | Risk | Mitigation |
| ------------ | ------------------------ | -------------------- |
| Bubble | Size hard to compare | Add size legend |
| Stacked Area | Overlapping trends | Limit to 4 series |
| Gauge | Takes space, little info | Use KPI card instead |
## Quick Reference Table
| Data Type | Wrong Chart | Right Chart | Why |
| ------------------------- | ------------- | ------------ | ------------------------- |
| Time series (many points) | Bar | Line | Lines show continuity |
| Geographic | Bar | Map | Spatial patterns visible |
| Small differences | Pie | Bar | Bars more precise |
| Composition over time | Multiple pies | Stacked area | Shows trend + composition |
| 10+ categories | Pie | Bar | Readable labels |
| Correlation | Line | Scatter | Line implies sequence |
```