ADR-012: Apply Vizro best practices for KPI cards and responsive design¶
Note: This ADR was originally numbered ADR-002 but was renumbered to ADR-012 during the 2026-01-28 namespace consolidation to resolve collision with ADR-002-cross-validation-strategy.md
Status: Approved Date: 2026-01-28 Deciders: @cloud-architect, @product-owner, HITL/Manager
Context¶
Current ITSM demo has UX issues identified by product-owner:
- KPI cards: Basic styling, no reference comparison, inconsistent icons
- Instruction text: On homepage instead of contextual tooltip
- Table pagination: Missing (infinite scroll causes performance issues with 74+ rows)
- Responsive design: Untested at 200% zoom (WCAG 2.1 AA requirement)
We need to align with Vizro best practices and accessibility standards.
Decision¶
Apply four UX improvements following Vizro design patterns:
1. KPI Card Styling (McKinsey Visual Vocabulary)¶
Use kpi_card_reference with:
- Icons: Material Icons (ticket, priority, calendar, alert)
- Reference comparison: Show delta vs target/baseline (e.g., "+5.2% vs. last week")
- Layout: vm.Grid(grid=[[0, 1, 2, 3]], col_gap='20px') for responsive spacing
- Min height: 120px to prevent text wrapping at 150%+ zoom
Pattern source: call-center/app.py:48-97
2. Contextual Tooltips¶
Move instruction from homepage text to KPI card header field:
# OLD: Homepage text
"Click any KPI card to filter the dashboard below."
# NEW: Contextual tooltip
vm.Figure(
header='💡 Click on a KPI card to filter the dashboard below.',
figure=kpi_card_reference(...)
)
Pattern source: bi-dashboard/app.py:132 (usa_map header example)
3. Table Pagination¶
Enable default 10 rows per page:
vm.AgGrid(
figure=dash_ag_grid(
data_frame=df,
dashGridOptions={
'pagination': True,
'paginationPageSize': 10,
'paginationAutoPageSize': False
}
)
)
Pattern source: kpi-dashboard/app.py:231
4. Responsive Design (25%-200% zoom)¶
Add viewport meta tag and CSS media queries:
/* 200% zoom */
@media (min-resolution: 192dpi) {
.kpi-card { font-size: 1.2rem; padding: 16px; }
}
/* 150% zoom */
@media (min-resolution: 144dpi) {
.kpi-card { padding: 12px; }
}
/* 50% zoom */
@media (max-resolution: 48dpi) {
.kpi-card { min-width: 200px; }
}
Test at 5 zoom levels: 25%, 50%, 100%, 150%, 200%
Consequences¶
Positive¶
- WCAG 2.1 AA compliant: 200% zoom requirement met (accessibility)
- Reduced cognitive load: Tooltip shows instruction in context (UX best practice)
- Better data navigation: Pagination prevents scroll fatigue with 74+ rows
- Consistent design system: Aligns with McKinsey Vizro Visual Vocabulary
- Performance: Pagination reduces DOM nodes from 74 to 10 (7.4x improvement)
Negative¶
- CSS complexity: Media queries add 15 LOC of styling code
- Testing overhead: Must validate 5 zoom levels (adds ~5min to E2E tests)
- Viewport constraint:
maximum-scale=2.0prevents zoom >200% (intentional tradeoff)
Risks¶
- Risk 1 (Text overflow at 200% zoom): Probability MEDIUM, Impact LOW
-
Mitigation: Playwright E2E screenshots at 200% zoom, CSS
text-overflow: ellipsis -
Risk 2 (Pagination breaks filter): Probability LOW, Impact MEDIUM
- Mitigation: Tier 3 E2E test validates "filter + pagination" interaction
Alternatives Considered¶
- Use Dash Bootstrap Components: Rejected because Vizro native components provide better theme consistency
- Disable zoom >150%: Rejected because WCAG 2.1 AA requires 200% support
- Client-side pagination only: Rejected because server-side pagination needed for 1000+ rows (future-proofing)
References¶
- WCAG 2.1 Success Criterion 1.4.4 (Resize text)
- Vizro kpi_card_reference API
- Material Icons
- Vizro theming guide
Evidence¶
- Responsive validation:
tmp/cloud-infrastructure/evidence/responsive-validation-{zoom}pct.png(5 screenshots) - Playwright test:
tests/e2e/test_itsm_responsive.spec.py - CSS source:
dashboards/itsm/shared/responsive.css