@bonnard/cli 0.2.16 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/bin/bon.mjs +254 -48
- package/dist/docs/topics/dashboards.components.md +246 -0
- package/dist/docs/topics/dashboards.examples.md +343 -0
- package/dist/docs/topics/dashboards.inputs.md +173 -0
- package/dist/docs/topics/dashboards.md +112 -0
- package/dist/docs/topics/dashboards.queries.md +112 -0
- package/dist/docs/topics/sdk.browser.md +1 -1
- package/dist/templates/claude/skills/bonnard-build-dashboard/SKILL.md +77 -39
- package/dist/templates/cursor/rules/bonnard-build-dashboard.mdc +76 -38
- package/dist/templates/shared/bonnard.md +3 -2
- package/dist/viewer.html +261 -0
- package/package.json +12 -2
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Components
|
|
2
|
+
|
|
3
|
+
> Chart and display components for rendering query results in dashboards.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Components are self-closing HTML-style tags that render query results as charts, tables, or KPI cards. Each component takes a `data` prop referencing a named query.
|
|
8
|
+
|
|
9
|
+
Choose the component that best fits your data:
|
|
10
|
+
|
|
11
|
+
- **BigValue** — single KPI number (total revenue, order count)
|
|
12
|
+
- **LineChart** — trends over time
|
|
13
|
+
- **BarChart** — comparing categories (vertical or horizontal)
|
|
14
|
+
- **AreaChart** — cumulative or stacked trends
|
|
15
|
+
- **PieChart** — proportional breakdown (best with 5-7 slices)
|
|
16
|
+
- **DataTable** — detailed rows for drilling into data
|
|
17
|
+
|
|
18
|
+
## Syntax
|
|
19
|
+
|
|
20
|
+
```markdown
|
|
21
|
+
<ComponentName data={query_name} prop="value" />
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- Components are self-closing (`/>`)
|
|
25
|
+
- `data` uses curly braces: `data={query_name}`
|
|
26
|
+
- Other props use quotes: `x="orders.city"`
|
|
27
|
+
- Boolean props can be shorthand: `horizontal`
|
|
28
|
+
|
|
29
|
+
## Component Reference
|
|
30
|
+
|
|
31
|
+
### BigValue
|
|
32
|
+
|
|
33
|
+
Displays a single KPI metric as a large number.
|
|
34
|
+
|
|
35
|
+
```markdown
|
|
36
|
+
<BigValue data={total_revenue} value="orders.total_revenue" title="Revenue" />
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
| Prop | Type | Required | Description |
|
|
40
|
+
|------|------|----------|-------------|
|
|
41
|
+
| `data` | query ref | Yes | Query name (should return a single row) |
|
|
42
|
+
| `value` | string | Yes | Fully qualified measure field name to display |
|
|
43
|
+
| `title` | string | No | Label above the value |
|
|
44
|
+
| `fmt` | string | No | Format preset or Excel code (e.g. `fmt="eur2"`, `fmt="$#,##0.00"`) |
|
|
45
|
+
|
|
46
|
+
### LineChart
|
|
47
|
+
|
|
48
|
+
Renders a line chart, typically for time series. Supports multiple y columns and series splitting.
|
|
49
|
+
|
|
50
|
+
```markdown
|
|
51
|
+
<LineChart data={monthly_revenue} x="orders.created_at" y="orders.total_revenue" title="Revenue Trend" />
|
|
52
|
+
<LineChart data={trend} x="orders.created_at" y="orders.total_revenue,orders.count" />
|
|
53
|
+
<LineChart data={revenue_by_type} x="orders.created_at" y="orders.total_revenue" series="orders.type" />
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
| Prop | Type | Required | Description |
|
|
57
|
+
|------|------|----------|-------------|
|
|
58
|
+
| `data` | query ref | Yes | Query name |
|
|
59
|
+
| `x` | string | Yes | Field for x-axis (typically a time dimension) |
|
|
60
|
+
| `y` | string | Yes | Field(s) for y-axis. Comma-separated for multiple (e.g. `y="orders.total_revenue,orders.count"`) |
|
|
61
|
+
| `title` | string | No | Chart title |
|
|
62
|
+
| `series` | string | No | Column to split data into separate colored lines |
|
|
63
|
+
| `type` | string | No | `"stacked"` for stacked lines (default: no stacking) |
|
|
64
|
+
| `yFmt` | string | No | Format preset or Excel code for tooltip values (e.g. `yFmt="eur2"`) |
|
|
65
|
+
|
|
66
|
+
### BarChart
|
|
67
|
+
|
|
68
|
+
Renders a vertical bar chart. Add `horizontal` for horizontal bars. Supports multi-series with stacked or grouped display.
|
|
69
|
+
|
|
70
|
+
```markdown
|
|
71
|
+
<BarChart data={revenue_by_city} x="orders.city" y="orders.total_revenue" />
|
|
72
|
+
<BarChart data={revenue_by_city} x="orders.city" y="orders.total_revenue" horizontal />
|
|
73
|
+
<BarChart data={revenue_by_type} x="orders.created_at" y="orders.total_revenue" series="orders.type" />
|
|
74
|
+
<BarChart data={revenue_by_type} x="orders.created_at" y="orders.total_revenue" series="orders.type" type="grouped" />
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
| Prop | Type | Required | Description |
|
|
78
|
+
|------|------|----------|-------------|
|
|
79
|
+
| `data` | query ref | Yes | Query name |
|
|
80
|
+
| `x` | string | Yes | Field for category axis |
|
|
81
|
+
| `y` | string | Yes | Field(s) for value axis. Comma-separated for multiple (e.g. `y="orders.total_revenue,orders.count"`) |
|
|
82
|
+
| `title` | string | No | Chart title |
|
|
83
|
+
| `horizontal` | boolean | No | Render as horizontal bar chart |
|
|
84
|
+
| `series` | string | No | Column to split data into separate colored bars |
|
|
85
|
+
| `type` | string | No | `"stacked"` (default) or `"grouped"` for multi-series display |
|
|
86
|
+
| `yFmt` | string | No | Format preset or Excel code for tooltip values (e.g. `yFmt="usd"`) |
|
|
87
|
+
|
|
88
|
+
### AreaChart
|
|
89
|
+
|
|
90
|
+
Renders a filled area chart. Supports series splitting and stacked areas.
|
|
91
|
+
|
|
92
|
+
```markdown
|
|
93
|
+
<AreaChart data={monthly_revenue} x="orders.created_at" y="orders.total_revenue" />
|
|
94
|
+
<AreaChart data={revenue_by_source} x="orders.created_at" y="orders.total_revenue" series="orders.source" type="stacked" />
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
| Prop | Type | Required | Description |
|
|
98
|
+
|------|------|----------|-------------|
|
|
99
|
+
| `data` | query ref | Yes | Query name |
|
|
100
|
+
| `x` | string | Yes | Field for x-axis |
|
|
101
|
+
| `y` | string | Yes | Field(s) for y-axis. Comma-separated for multiple (e.g. `y="orders.total_revenue,orders.count"`) |
|
|
102
|
+
| `title` | string | No | Chart title |
|
|
103
|
+
| `series` | string | No | Column to split data into separate colored areas |
|
|
104
|
+
| `type` | string | No | `"stacked"` for stacked areas (default: no stacking) |
|
|
105
|
+
| `yFmt` | string | No | Format preset or Excel code for tooltip values (e.g. `yFmt="pct1"`) |
|
|
106
|
+
|
|
107
|
+
### PieChart
|
|
108
|
+
|
|
109
|
+
Renders a pie/donut chart.
|
|
110
|
+
|
|
111
|
+
```markdown
|
|
112
|
+
<PieChart data={by_status} name="orders.status" value="orders.count" title="Order Status" />
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
| Prop | Type | Required | Description |
|
|
116
|
+
|------|------|----------|-------------|
|
|
117
|
+
| `data` | query ref | Yes | Query name |
|
|
118
|
+
| `name` | string | Yes | Field for slice labels |
|
|
119
|
+
| `value` | string | Yes | Field for slice values |
|
|
120
|
+
| `title` | string | No | Chart title |
|
|
121
|
+
|
|
122
|
+
### DataTable
|
|
123
|
+
|
|
124
|
+
Renders query results as a sortable, paginated table. Click any column header to sort ascending/descending.
|
|
125
|
+
|
|
126
|
+
```markdown
|
|
127
|
+
<DataTable data={top_products} />
|
|
128
|
+
<DataTable data={top_products} columns="orders.category,orders.total_revenue,orders.count" />
|
|
129
|
+
<DataTable data={top_products} rows="25" />
|
|
130
|
+
<DataTable data={top_products} rows="all" />
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
| Prop | Type | Required | Description |
|
|
134
|
+
|------|------|----------|-------------|
|
|
135
|
+
| `data` | query ref | Yes | Query name |
|
|
136
|
+
| `columns` | string | No | Comma-separated list of columns to show (default: all) |
|
|
137
|
+
| `title` | string | No | Table title |
|
|
138
|
+
| `fmt` | string | No | Column format map: `fmt="orders.total_revenue:eur2,orders.created_at:shortdate"` |
|
|
139
|
+
| `rows` | string | No | Rows per page. Default `10`. Use `rows="all"` to disable pagination. |
|
|
140
|
+
|
|
141
|
+
**Sorting:** Click a column header to sort ascending. Click again to sort descending. Null values always sort to the end. Numbers sort numerically, strings sort case-insensitively.
|
|
142
|
+
|
|
143
|
+
**Formatting:** Numbers right-align with tabular figures. Dates auto-detect and won't wrap. Use `fmt` for explicit formatting per column.
|
|
144
|
+
|
|
145
|
+
## Layout
|
|
146
|
+
|
|
147
|
+
### Auto BigValue Grouping
|
|
148
|
+
|
|
149
|
+
Consecutive `<BigValue>` components are automatically wrapped in a responsive grid — no `<Grid>` tag needed:
|
|
150
|
+
|
|
151
|
+
```markdown
|
|
152
|
+
<BigValue data={total_revenue} value="orders.total_revenue" title="Revenue" />
|
|
153
|
+
<BigValue data={order_count} value="orders.count" title="Orders" />
|
|
154
|
+
<BigValue data={avg_order} value="orders.avg_order_value" title="Avg Order" />
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
This renders as a 3-column row. The grid auto-sizes up to 4 columns based on the number of consecutive BigValues. For more control, use an explicit `<Grid>` tag.
|
|
158
|
+
|
|
159
|
+
### Grid
|
|
160
|
+
|
|
161
|
+
Wrap components in a `<Grid>` tag to arrange them in columns:
|
|
162
|
+
|
|
163
|
+
```markdown
|
|
164
|
+
<Grid cols="3">
|
|
165
|
+
<BigValue data={total_orders} value="orders.count" title="Orders" />
|
|
166
|
+
<BigValue data={total_revenue} value="orders.total_revenue" title="Revenue" />
|
|
167
|
+
<BigValue data={avg_order} value="orders.avg_order_value" title="Avg Order" />
|
|
168
|
+
</Grid>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
| Prop | Type | Default | Description |
|
|
172
|
+
|------|------|---------|-------------|
|
|
173
|
+
| `cols` | string | `"2"` | Number of columns in the grid |
|
|
174
|
+
|
|
175
|
+
### Layout Best Practices
|
|
176
|
+
|
|
177
|
+
**Use `##` for sections, not `#`.** The `#` heading renders very large and wastes vertical space. Use `##` for section titles and `###` for subsections. Reserve `#` for the dashboard title only (which is set in frontmatter, not in the body).
|
|
178
|
+
|
|
179
|
+
**Group related charts side by side.** Wrap pairs of charts in `<Grid cols="2">` to avoid long vertical scrolling:
|
|
180
|
+
|
|
181
|
+
```markdown
|
|
182
|
+
<Grid cols="2">
|
|
183
|
+
<BarChart data={by_channel} x="orders.channel" y="orders.total_revenue" title="By Channel" />
|
|
184
|
+
<BarChart data={by_city} x="orders.city" y="orders.total_revenue" title="By City" horizontal />
|
|
185
|
+
</Grid>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Start each section with KPIs.** Place `<BigValue>` cards at the top of a section for at-a-glance metrics, then follow with charts for detail.
|
|
189
|
+
|
|
190
|
+
**Only Grid together components of similar height.** Don't mix a `<BigValue>` with a chart in the same `<Grid>` row — the grid stretches both cells to the tallest item, leaving the BigValue card with a large empty area. Instead, place KPIs in their own row (consecutive BigValues auto-group) and pair charts with other charts of similar size.
|
|
191
|
+
|
|
192
|
+
**Keep it compact.** A good dashboard fits key information in 2-3 screens of scrolling. Use Grids, concise titles, and avoid unnecessary headings between every chart.
|
|
193
|
+
|
|
194
|
+
## Formatting
|
|
195
|
+
|
|
196
|
+
Values are auto-formatted by default — numbers get locale grouping (1,234.56), dates display as "13 Jan 2025", and nulls show as "—". Override with named presets for common currencies and percentages, or use raw Excel format codes for full control.
|
|
197
|
+
|
|
198
|
+
### Format Presets
|
|
199
|
+
|
|
200
|
+
| Preset | Excel code | Example output |
|
|
201
|
+
|--------|-----------|---------------|
|
|
202
|
+
| `num0` | `#,##0` | 1,234 |
|
|
203
|
+
| `num1` | `#,##0.0` | 1,234.6 |
|
|
204
|
+
| `num2` | `#,##0.00` | 1,234.56 |
|
|
205
|
+
| `usd` | `$#,##0` | $1,234 |
|
|
206
|
+
| `usd2` | `$#,##0.00` | $1,234.56 |
|
|
207
|
+
| `eur` | `#,##0 "€"` | 1,234 € |
|
|
208
|
+
| `eur2` | `#,##0.00 "€"` | 1,234.56 € |
|
|
209
|
+
| `gbp` | `£#,##0` | £1,234 |
|
|
210
|
+
| `gbp2` | `£#,##0.00` | £1,234.56 |
|
|
211
|
+
| `chf` | `"CHF "#,##0` | CHF 1,234 |
|
|
212
|
+
| `chf2` | `"CHF "#,##0.00` | CHF 1,234.56 |
|
|
213
|
+
| `pct` | `0%` | 45% |
|
|
214
|
+
| `pct1` | `0.0%` | 45.1% |
|
|
215
|
+
| `pct2` | `0.00%` | 45.12% |
|
|
216
|
+
| `shortdate` | `d mmm yyyy` | 13 Jan 2025 |
|
|
217
|
+
| `longdate` | `d mmmm yyyy` | 13 January 2025 |
|
|
218
|
+
| `monthyear` | `mmm yyyy` | Jan 2025 |
|
|
219
|
+
|
|
220
|
+
Any string that isn't a preset name is treated as a raw Excel format code (ECMA-376). For example: `fmt="orders.total_revenue:$#,##0.00"`.
|
|
221
|
+
|
|
222
|
+
Note: Percentage presets (`pct`, `pct1`, `pct2`) multiply by 100 per Excel convention — 0.45 displays as "45%".
|
|
223
|
+
|
|
224
|
+
### Usage Examples
|
|
225
|
+
|
|
226
|
+
```markdown
|
|
227
|
+
<!-- BigValue with currency -->
|
|
228
|
+
<BigValue data={total_revenue} value="orders.total_revenue" title="Revenue" fmt="eur2" />
|
|
229
|
+
|
|
230
|
+
<!-- DataTable with per-column formatting -->
|
|
231
|
+
<DataTable data={sales} fmt="orders.total_revenue:usd2,orders.created_at:shortdate,orders.margin:pct1" />
|
|
232
|
+
|
|
233
|
+
<!-- Chart with formatted tooltips -->
|
|
234
|
+
<BarChart data={monthly} x="orders.created_at" y="orders.total_revenue" yFmt="usd" />
|
|
235
|
+
<LineChart data={trend} x="orders.created_at" y="orders.growth" yFmt="pct1" />
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Field Names
|
|
239
|
+
|
|
240
|
+
All field names in component props must be **fully qualified** with the view or cube name — the same format used in query blocks. For example, use `value="orders.total_revenue"` not `value="total_revenue"`.
|
|
241
|
+
|
|
242
|
+
## See Also
|
|
243
|
+
|
|
244
|
+
- [Queries](dashboards.queries) — query syntax and properties
|
|
245
|
+
- [Examples](dashboards.examples) — complete dashboard examples
|
|
246
|
+
- [Dashboards](dashboards) — overview and deployment
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
> Complete dashboard examples showing common patterns.
|
|
4
|
+
|
|
5
|
+
## Revenue Overview Dashboard
|
|
6
|
+
|
|
7
|
+
The most common dashboard pattern: KPI cards at the top for at-a-glance metrics, a time series chart for trends, and a bar chart with data table for category breakdown.
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
---
|
|
11
|
+
title: Revenue Overview
|
|
12
|
+
description: Monthly revenue trends and breakdowns
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Revenue Overview
|
|
16
|
+
|
|
17
|
+
` ``query total_revenue
|
|
18
|
+
measures: [orders.total_revenue]
|
|
19
|
+
` ``
|
|
20
|
+
|
|
21
|
+
` ``query order_count
|
|
22
|
+
measures: [orders.count]
|
|
23
|
+
` ``
|
|
24
|
+
|
|
25
|
+
` ``query avg_order
|
|
26
|
+
measures: [orders.avg_order_value]
|
|
27
|
+
` ``
|
|
28
|
+
|
|
29
|
+
<Grid cols="3">
|
|
30
|
+
<BigValue data={total_revenue} value="orders.total_revenue" title="Total Revenue" />
|
|
31
|
+
<BigValue data={order_count} value="orders.count" title="Orders" />
|
|
32
|
+
<BigValue data={avg_order} value="orders.avg_order_value" title="Avg Order" />
|
|
33
|
+
</Grid>
|
|
34
|
+
|
|
35
|
+
## Monthly Trend
|
|
36
|
+
|
|
37
|
+
` ``query monthly_revenue
|
|
38
|
+
measures: [orders.total_revenue]
|
|
39
|
+
timeDimension:
|
|
40
|
+
dimension: orders.created_at
|
|
41
|
+
granularity: month
|
|
42
|
+
dateRange: [2025-01-01, 2025-12-31]
|
|
43
|
+
` ``
|
|
44
|
+
|
|
45
|
+
<LineChart data={monthly_revenue} x="orders.created_at" y="orders.total_revenue" title="Monthly Revenue" />
|
|
46
|
+
|
|
47
|
+
## By Category
|
|
48
|
+
|
|
49
|
+
` ``query by_category
|
|
50
|
+
measures: [orders.total_revenue, orders.count]
|
|
51
|
+
dimensions: [orders.category]
|
|
52
|
+
orderBy:
|
|
53
|
+
orders.total_revenue: desc
|
|
54
|
+
` ``
|
|
55
|
+
|
|
56
|
+
<BarChart data={by_category} x="orders.category" y="orders.total_revenue" title="Revenue by Category" />
|
|
57
|
+
<DataTable data={by_category} />
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Sales Pipeline Dashboard
|
|
61
|
+
|
|
62
|
+
A status-focused dashboard using a pie chart for proportional breakdown, a horizontal bar chart for ranking, and filters to drill into a specific segment.
|
|
63
|
+
|
|
64
|
+
```markdown
|
|
65
|
+
---
|
|
66
|
+
title: Sales Pipeline
|
|
67
|
+
description: Order status breakdown and city analysis
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
# Sales Pipeline
|
|
71
|
+
|
|
72
|
+
` ``query by_status
|
|
73
|
+
measures: [orders.count]
|
|
74
|
+
dimensions: [orders.status]
|
|
75
|
+
` ``
|
|
76
|
+
|
|
77
|
+
<PieChart data={by_status} name="orders.status" value="orders.count" title="Order Status" />
|
|
78
|
+
|
|
79
|
+
## Top Cities
|
|
80
|
+
|
|
81
|
+
` ``query top_cities
|
|
82
|
+
measures: [orders.total_revenue, orders.count]
|
|
83
|
+
dimensions: [orders.city]
|
|
84
|
+
orderBy:
|
|
85
|
+
orders.total_revenue: desc
|
|
86
|
+
limit: 10
|
|
87
|
+
` ``
|
|
88
|
+
|
|
89
|
+
<BarChart data={top_cities} x="orders.city" y="orders.total_revenue" horizontal />
|
|
90
|
+
<DataTable data={top_cities} />
|
|
91
|
+
|
|
92
|
+
## Completed Orders Over Time
|
|
93
|
+
|
|
94
|
+
` ``query completed_trend
|
|
95
|
+
measures: [orders.total_revenue]
|
|
96
|
+
timeDimension:
|
|
97
|
+
dimension: orders.created_at
|
|
98
|
+
granularity: week
|
|
99
|
+
dateRange: [2025-01-01, 2025-06-30]
|
|
100
|
+
filters:
|
|
101
|
+
- dimension: orders.status
|
|
102
|
+
operator: equals
|
|
103
|
+
values: [completed]
|
|
104
|
+
` ``
|
|
105
|
+
|
|
106
|
+
<AreaChart data={completed_trend} x="orders.created_at" y="orders.total_revenue" title="Completed Order Revenue" />
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Multi-Series Dashboard
|
|
110
|
+
|
|
111
|
+
When you need to compare segments side-by-side, use the `series` prop to split data by a dimension into colored segments. This example shows stacked bars, grouped bars, multi-line, and stacked area — all from the same data.
|
|
112
|
+
|
|
113
|
+
```markdown
|
|
114
|
+
---
|
|
115
|
+
title: Revenue by Channel
|
|
116
|
+
description: Multi-series charts showing revenue breakdown by sales channel
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
# Revenue by Channel
|
|
120
|
+
|
|
121
|
+
` ``query revenue_by_channel
|
|
122
|
+
measures: [orders.total_revenue]
|
|
123
|
+
dimensions: [orders.channel]
|
|
124
|
+
timeDimension:
|
|
125
|
+
dimension: orders.created_at
|
|
126
|
+
granularity: month
|
|
127
|
+
dateRange: [2025-01-01, 2025-12-31]
|
|
128
|
+
` ``
|
|
129
|
+
|
|
130
|
+
## Stacked Bar (default)
|
|
131
|
+
|
|
132
|
+
<BarChart data={revenue_by_channel} x="orders.created_at" y="orders.total_revenue" series="orders.channel" title="Revenue by Channel" />
|
|
133
|
+
|
|
134
|
+
## Grouped Bar
|
|
135
|
+
|
|
136
|
+
<BarChart data={revenue_by_channel} x="orders.created_at" y="orders.total_revenue" series="orders.channel" type="grouped" title="Revenue by Channel (Grouped)" />
|
|
137
|
+
|
|
138
|
+
## Multi-Line
|
|
139
|
+
|
|
140
|
+
` ``query trend
|
|
141
|
+
measures: [orders.total_revenue, orders.count]
|
|
142
|
+
timeDimension:
|
|
143
|
+
dimension: orders.created_at
|
|
144
|
+
granularity: month
|
|
145
|
+
dateRange: [2025-01-01, 2025-12-31]
|
|
146
|
+
` ``
|
|
147
|
+
|
|
148
|
+
<LineChart data={trend} x="orders.created_at" y="orders.total_revenue,orders.count" title="Revenue vs Orders" />
|
|
149
|
+
|
|
150
|
+
## Stacked Area by Channel
|
|
151
|
+
|
|
152
|
+
<AreaChart data={revenue_by_channel} x="orders.created_at" y="orders.total_revenue" series="orders.channel" type="stacked" title="Revenue by Channel" />
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Formatted Dashboard
|
|
156
|
+
|
|
157
|
+
Use format presets to display currencies, percentages, and number styles consistently across KPIs, charts, and tables.
|
|
158
|
+
|
|
159
|
+
```markdown
|
|
160
|
+
---
|
|
161
|
+
title: Sales Performance
|
|
162
|
+
description: Formatted revenue metrics and trends
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
# Sales Performance
|
|
166
|
+
|
|
167
|
+
` ``query totals
|
|
168
|
+
measures: [orders.total_revenue, orders.count, orders.avg_order_value]
|
|
169
|
+
` ``
|
|
170
|
+
|
|
171
|
+
<Grid cols="3">
|
|
172
|
+
<BigValue data={totals} value="orders.total_revenue" title="Revenue" fmt="eur2" />
|
|
173
|
+
<BigValue data={totals} value="orders.count" title="Orders" fmt="num0" />
|
|
174
|
+
<BigValue data={totals} value="orders.avg_order_value" title="Avg Order" fmt="eur2" />
|
|
175
|
+
</Grid>
|
|
176
|
+
|
|
177
|
+
## Revenue Trend
|
|
178
|
+
|
|
179
|
+
` ``query monthly
|
|
180
|
+
measures: [orders.total_revenue]
|
|
181
|
+
timeDimension:
|
|
182
|
+
dimension: orders.created_at
|
|
183
|
+
granularity: month
|
|
184
|
+
dateRange: [2025-01-01, 2025-12-31]
|
|
185
|
+
` ``
|
|
186
|
+
|
|
187
|
+
<LineChart data={monthly} x="orders.created_at" y="orders.total_revenue" title="Monthly Revenue" yFmt="eur" />
|
|
188
|
+
|
|
189
|
+
## Detail Table
|
|
190
|
+
|
|
191
|
+
` ``query details
|
|
192
|
+
measures: [orders.total_revenue, orders.count]
|
|
193
|
+
dimensions: [orders.category]
|
|
194
|
+
orderBy:
|
|
195
|
+
orders.total_revenue: desc
|
|
196
|
+
` ``
|
|
197
|
+
|
|
198
|
+
<DataTable data={details} fmt="orders.total_revenue:eur2,orders.count:num0" />
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Interactive Dashboard
|
|
202
|
+
|
|
203
|
+
Combine a DateRange picker and Dropdown filter to let viewers explore the data. Filter state syncs to the URL, so shared links preserve the exact filtered view.
|
|
204
|
+
|
|
205
|
+
```markdown
|
|
206
|
+
---
|
|
207
|
+
title: Interactive Sales
|
|
208
|
+
description: Sales dashboard with date and channel filters
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
# Interactive Sales
|
|
212
|
+
|
|
213
|
+
<DateRange name="period" default="last-6-months" label="Time Period" />
|
|
214
|
+
<Dropdown name="channel" dimension="orders.channel" data={channels} queries="trend,by_city" label="Channel" />
|
|
215
|
+
|
|
216
|
+
` ``query channels
|
|
217
|
+
dimensions: [orders.channel]
|
|
218
|
+
` ``
|
|
219
|
+
|
|
220
|
+
` ``query kpis
|
|
221
|
+
measures: [orders.total_revenue, orders.count]
|
|
222
|
+
` ``
|
|
223
|
+
|
|
224
|
+
<Grid cols="2">
|
|
225
|
+
<BigValue data={kpis} value="orders.total_revenue" title="Revenue" fmt="eur2" />
|
|
226
|
+
<BigValue data={kpis} value="orders.count" title="Orders" fmt="num0" />
|
|
227
|
+
</Grid>
|
|
228
|
+
|
|
229
|
+
## Revenue Trend
|
|
230
|
+
|
|
231
|
+
` ``query trend
|
|
232
|
+
measures: [orders.total_revenue]
|
|
233
|
+
timeDimension:
|
|
234
|
+
dimension: orders.created_at
|
|
235
|
+
granularity: month
|
|
236
|
+
` ``
|
|
237
|
+
|
|
238
|
+
<LineChart data={trend} x="orders.created_at" y="orders.total_revenue" title="Monthly Revenue" yFmt="eur" />
|
|
239
|
+
|
|
240
|
+
## By City
|
|
241
|
+
|
|
242
|
+
` ``query by_city
|
|
243
|
+
measures: [orders.total_revenue]
|
|
244
|
+
dimensions: [orders.city]
|
|
245
|
+
orderBy:
|
|
246
|
+
orders.total_revenue: desc
|
|
247
|
+
limit: 10
|
|
248
|
+
` ``
|
|
249
|
+
|
|
250
|
+
<BarChart data={by_city} x="orders.city" y="orders.total_revenue" title="Top Cities" yFmt="eur" />
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
The `<DateRange>` automatically applies to all queries with a `timeDimension` (here: `trend`). The `<Dropdown>` filters `trend` and `by_city` by channel. The `channels` query populates the dropdown and is never filtered by it.
|
|
254
|
+
|
|
255
|
+
## Compact Multi-Section Dashboard
|
|
256
|
+
|
|
257
|
+
A dashboard with multiple sections, side-by-side charts, and compact layout. Uses `##` headings (not `#`), `<Grid>` for horizontal grouping, and keeps all queries near the components that use them.
|
|
258
|
+
|
|
259
|
+
```markdown
|
|
260
|
+
---
|
|
261
|
+
title: Operations Overview
|
|
262
|
+
description: KPIs, trends, and breakdowns across channels and cities
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
<DateRange name="period" default="last-30-days" label="Period" />
|
|
266
|
+
|
|
267
|
+
` ``query channels
|
|
268
|
+
dimensions: [orders.channel]
|
|
269
|
+
` ``
|
|
270
|
+
|
|
271
|
+
<Dropdown name="channel" dimension="orders.channel" data={channels} queries="kpis,trend,by_city" label="Channel" />
|
|
272
|
+
|
|
273
|
+
## Key Metrics
|
|
274
|
+
|
|
275
|
+
` ``query kpis
|
|
276
|
+
measures: [orders.total_revenue, orders.count, orders.avg_order_value]
|
|
277
|
+
` ``
|
|
278
|
+
|
|
279
|
+
<BigValue data={kpis} value="orders.total_revenue" title="Revenue" fmt="eur" />
|
|
280
|
+
<BigValue data={kpis} value="orders.count" title="Orders" fmt="num0" />
|
|
281
|
+
<BigValue data={kpis} value="orders.avg_order_value" title="Avg Order" fmt="eur2" />
|
|
282
|
+
|
|
283
|
+
## Trends & Breakdown
|
|
284
|
+
|
|
285
|
+
` ``query trend
|
|
286
|
+
measures: [orders.total_revenue]
|
|
287
|
+
timeDimension:
|
|
288
|
+
dimension: orders.created_at
|
|
289
|
+
granularity: week
|
|
290
|
+
` ``
|
|
291
|
+
|
|
292
|
+
` ``query by_channel
|
|
293
|
+
measures: [orders.total_revenue]
|
|
294
|
+
dimensions: [orders.channel]
|
|
295
|
+
orderBy:
|
|
296
|
+
orders.total_revenue: desc
|
|
297
|
+
` ``
|
|
298
|
+
|
|
299
|
+
<Grid cols="2">
|
|
300
|
+
<LineChart data={trend} x="orders.created_at" y="orders.total_revenue" title="Weekly Revenue" yFmt="eur" />
|
|
301
|
+
<BarChart data={by_channel} x="orders.channel" y="orders.total_revenue" title="By Channel" yFmt="eur" />
|
|
302
|
+
</Grid>
|
|
303
|
+
|
|
304
|
+
## Top Cities
|
|
305
|
+
|
|
306
|
+
` ``query by_city
|
|
307
|
+
measures: [orders.total_revenue, orders.count]
|
|
308
|
+
dimensions: [orders.city]
|
|
309
|
+
orderBy:
|
|
310
|
+
orders.total_revenue: desc
|
|
311
|
+
limit: 10
|
|
312
|
+
` ``
|
|
313
|
+
|
|
314
|
+
<Grid cols="2">
|
|
315
|
+
<BarChart data={by_city} x="orders.city" y="orders.total_revenue" title="Revenue by City" horizontal yFmt="eur" />
|
|
316
|
+
<DataTable data={by_city} fmt="orders.total_revenue:eur,orders.count:num0" />
|
|
317
|
+
</Grid>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Key patterns:
|
|
321
|
+
- **`##` headings** for sections — compact, no oversized H1s
|
|
322
|
+
- **Consecutive `<BigValue>`** auto-groups into a row (no Grid needed)
|
|
323
|
+
- **`<Grid cols="2">`** pairs a chart with a table or two charts side by side
|
|
324
|
+
- **Queries defined before their Grid** — keeps the layout clean and components grouped
|
|
325
|
+
|
|
326
|
+
## Tips
|
|
327
|
+
|
|
328
|
+
- **Start with KPIs**: Use `BigValue` at the top for key metrics — consecutive BigValues auto-group into a row
|
|
329
|
+
- **One query per chart**: Each component gets its own query — keep them focused
|
|
330
|
+
- **Use `##` headings**: Reserve `#` for the dashboard title (in frontmatter). Use `##` for sections
|
|
331
|
+
- **Use views**: Prefer view names over cube names when available
|
|
332
|
+
- **Name queries descriptively**: `monthly_revenue` is better than `q1`
|
|
333
|
+
- **Limit large datasets**: Add `limit` to dimension queries to avoid oversized charts
|
|
334
|
+
- **Time series**: Always use `timeDimension` with `granularity` for time-based charts
|
|
335
|
+
- **Multi-series**: Use `series="cube.column"` to split data by a dimension. For bars, default is stacked; use `type="grouped"` for side-by-side
|
|
336
|
+
- **Multiple y columns**: Use comma-separated values like `y="orders.revenue,orders.cases"` to show multiple measures on one chart
|
|
337
|
+
- **Side-by-side charts**: Wrap pairs in `<Grid cols="2">` to reduce vertical scrolling
|
|
338
|
+
|
|
339
|
+
## See Also
|
|
340
|
+
|
|
341
|
+
- [Dashboards](dashboards) — overview and deployment
|
|
342
|
+
- [Queries](dashboards.queries) — query syntax and properties
|
|
343
|
+
- [Components](dashboards.components) — chart and display components
|