@risqbase-inc/ui-components · v2.2.0

Patterns

Composite recipes - pre-composed UI worth giving a name.

Each recipe specifies a composition the system endorses: which components, in which arrangement, for which problem, with which voice. Recipes are how the system answers questions like "how do we lay out a dashboard row?" without re-deciding every time. Spec §8.17.

dashboard-chart-row

Dashboard chart row

12-column grid · metric-card + sparkline + horizontal-bar · responsive stacking.

public stable
Open DPIAs147↑ 12 vs last month
Coverage87.2%↑ 4.1 pts
Avg time-to-sign4.2 d↓ 0.8 d
Fines YTD€0→ no change

Schema (§20.0)

id
dashboard-chart-row
visibility
PUBLIC
status
stable
problem
How do we render a top-of-dashboard summary that lets a reader compare 3–4 KPIs at a glance?
when to use
Top-fold of any dashboard. 3–4 metrics of comparable importance. Each metric must accept a delta + period caption.
when not to use
Fewer than 3 metrics (use single KPI card). More than 6 (overwhelm; reach for a small-multiples grid). Metric of incomparable type (count + currency + percent + duration - collapse to count + percent only and put the rest in detail).
composed of
Metric card (§7.10) × n · sparkline (§8.1.1 time)
layout
12-column grid. Each card spans 3 (4 cards · default), 4 (3 cards), or 6 (2 cards). Responsive: stack to 1 column at <640px.
variants
comparison-mode · score-mode (replaces metric card with gauge)
keyboard
Cards are Tab-navigable when interactive. Sparkline focuses on Tab.
voice examples
Tied to template_id 10.5.5 (help text). Each card title sentence-case verb-or-noun; delta uses arrows + tabular-nums per §10.3.3.2.
accessibility
Per-card aria-label reads as "{title}: {value} {delta description}".
last reviewed
2026-05-07 (v4.2)

time-comparison-chart

Time comparison chart

Line (2 series) + metric card + sparkbar · vertical stack.

public stable

Assessments completed

Trend · 12 months

Plan Actual
YTD delta+38%↑ vs plan

Schema (§20.0)

id
time-comparison-chart
problem
How do we show plan-vs-actual or this-period-vs-last over time, with the delta foregrounded?
when to use
Two time-series of the same metric, ≤24 data points. Reader cares about the delta as much as the trend.
when not to use
More than 2 series (use small-multiples line). Categorical x-axis (use grouped bar instead).
composed of
Line × 2 series · Metric card · Sparkbar (delta-mode variant)
variants
delta-mode (paired-bar of period-by-period delta) · annotation-mode (RuleMark events overlaid)
voice examples
Title: "{metric} · {period}". Caption sentence-case. Delta: ↑/↓ {magnitude} vs {comparator}. Tied to template_id 10.5.3.
accessibility
Data-table fallback toggleable with t. Both series carry aria-label from the legend.
last reviewed
2026-05-07 (v4.2)

distribution-drilldown

Distribution drilldown

Histogram + box-plot + bar-horizontal + metric card · 7:5 split layout.

public stable

Time-to-completion (days)

Distribution · 240 assessments

Median4.2 dP95 8.6 d

Schema (§20.0)

id
distribution-drilldown
problem
How do we show a distribution AND let the reader drill into a specific bin?
when to use
Continuous variable with ≥50 observations. Reader wants to see shape + summary + outliers, then click into a slice.
when not to use
n < 30 (use bar chart instead). Two-dimensional distribution (use heatmap).
composed of
Histogram · Box plot · Bar (horizontal) for binned drilldown · Metric card
layout
7:5 horizontal split desktop · stack to vertical <800px
variants
table-detail (replaces bar with paginated table) · filter-bound (histogram clicks drive surrounding filters)
voice examples
Stat language: median, P95, IQR - defined per glossary §10.6. Tied to template_id 10.8.1 (AI-hedging where IRIS surfaces stats).
accessibility
Histogram bins focusable via arrow keys. Data-table toggle t.
last reviewed
2026-05-07 (v4.2)

motion-preference

Motion preference

Settings-surface toggle for reduced motion · MotionProvider + labelled switch · new in v4.4 (D-110).

Layer 1 · core beta

Reduce motion

Fewer animations, same information. Currently following your system setting.

Schema (§20.0)

id
motion-preference
problem
Users need an in-product way to reduce animation without changing their OS setting — and an escape hatch to re-enable motion when the OS asks for reduced.
when to use
Any product settings surface. The OS prefers-reduced-motion signal is the default; the explicit choice (persisted to risqbase:motion) overrides it in both directions.
when not to use
Don't ship a toggle that only affects some components, and never override the OS reduce-motion signal silently.
composed of
MotionProvider (app root) · labelled switch built from Button/IconButton + text · setMotionPreference('full' | 'reduced' | null)
css contract
data-motion="full | reduced" on the provider wrapper; central [data-motion="reduced"] rules in tokens.css; scanner rule R13 gates component animation.
voice examples
"Reduce motion — fewer animations, same information." · "Following your system setting." Tied to template_id 10.5.5.
accessibility
WCAG 2.3.3 Animation from Interactions; resolution order documented in src/core/MotionProvider/accessibility.md.
machine-readable
last reviewed
2026-06-10 (v4.4)

Recipe schema

Every recipe authored to the same §20.0 schema. Editors can grep for "patterns/*.mdx" + assert each carries template_id + voice_examples per §20.0.1.

// docs/patterns/<recipe-id>.mdx
---
id: dashboard-chart-row
title: Dashboard chart row
visibility: PUBLIC
status: stable
problem: |
  How do we render a top-of-dashboard summary…
when_to_use: |
  Top-fold of any dashboard…
when_not_to_use: |
  Fewer than 3 metrics…
composed_of:
  - Metric / KPI card (§7.10)
  - Sparkline (§8.1.1 time)
layout: |
  12-column grid…
variants:
  - id: comparison-mode
    description: …
  - id: score-mode
    description: …
voice_examples:
  - template_id: 10.5.5
    context: card-title
    rendered: "Open DPIAs"
  - template_id: 10.5.5
    context: card-delta
    rendered: "↑ 12 vs last month"
keyboard: |
  Tab into cards…
accessibility: |
  Per-card aria-label…
last_reviewed: 2026-05-07
owner: G4
---

(Body content - usage examples, code snippets, anti-patterns.)

voice_examples binding (§20.0.1)

Every voice_examples entry must carry a template_id matching ^10\.[58]\.\d+$ - referencing a real template from spec §10.5 or §10.8. The CI gate lint:recipes-voice enforces this. Without the binding, the glossary is decorative; with it, copy on every shipped surface is testably the same word, the same sentence shape, the same hedge.