Skip to content

Commit 0479261

Browse files
committed
docs(spec,ui): regenerate dashboard reference + document the widget query options (#3588)
`content/docs/references/ui/dashboard.mdx` is generated from the spec and went stale when `DashboardWidgetOptionsSchema` was added — CI's generated-artifact drift check caught it. Also rewrites the hand-written `options` row in the dashboards guide, which described the bag as "Additional display options". That description is what let this bug happen: four of its keys change the compiled query, and an author had no way to know which. The guide now lists the five declared keys with their effects and the behavioural notes that are easy to get wrong (an unprojectable `sortBy` is rejected, a bare `limit` orders by dimensions first, a derived measure is a valid sort key, a funnel without a declared stage order falls back to value-descending). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SEZLBGyNoJMLvtGPqsMPRC
1 parent 7bb7830 commit 0479261

2 files changed

Lines changed: 62 additions & 4 deletions

File tree

content/docs/references/ui/dashboard.mdx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ Color variant for dashboard widgets (e.g., KPI cards).
1414
## TypeScript Usage
1515

1616
```typescript
17-
import { Dashboard, DashboardHeader, DashboardHeaderAction, DashboardWidget, GlobalFilter, GlobalFilterOptionsFrom, WidgetActionType, WidgetColorVariant } from '@objectstack/spec/ui';
18-
import type { Dashboard, DashboardHeader, DashboardHeaderAction, DashboardWidget, GlobalFilter, GlobalFilterOptionsFrom, WidgetActionType, WidgetColorVariant } from '@objectstack/spec/ui';
17+
import { Dashboard, DashboardHeader, DashboardHeaderAction, DashboardWidget, DashboardWidgetOptions, GlobalFilter, GlobalFilterOptionsFrom, WidgetActionType, WidgetColorVariant } from '@objectstack/spec/ui';
18+
import type { Dashboard, DashboardHeader, DashboardHeaderAction, DashboardWidget, DashboardWidgetOptions, GlobalFilter, GlobalFilterOptionsFrom, WidgetActionType, WidgetColorVariant } from '@objectstack/spec/ui';
1919

2020
// Validate data
2121
const result = Dashboard.parse(data);
@@ -107,13 +107,30 @@ Dashboard header action
107107
| **dimensions** | `string[]` | optional | Dimension names — X/group/split |
108108
| **values** | `string[]` || Measure names — Y (at least one) |
109109
| **layout** | `{ x: number; y: number; w: number; h: number }` | optional | Grid layout position (auto-flowed when omitted) |
110-
| **options** | `any` | optional | Widget specific configuration |
110+
| **options** | `Record<string, any>` | optional | Widget specific configuration |
111111
| **filterBindings** | `Record<string, string \| 'false'>` | optional | Per-widget dashboard-filter bindings: filter name → this widget's field, or false to opt out |
112112
| **suppressWarnings** | `string[]` | optional | Build diagnostic rule ids suppressed on this widget |
113113
| **responsive** | `{ breakpoint?: Enum<'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl'>; hiddenOn?: Enum<'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl'>[]; columns?: object; order?: object }` | optional | Responsive layout configuration |
114114
| **aria** | `{ ariaLabel?: string; ariaDescribedBy?: string; role?: string }` | optional | ARIA accessibility attributes |
115115

116116

117+
---
118+
119+
## DashboardWidgetOptions
120+
121+
Widget configuration — declared query keys + open renderer extras
122+
123+
### Properties
124+
125+
| Property | Type | Required | Description |
126+
| :--- | :--- | :--- | :--- |
127+
| **dateGranularity** | `Enum<'day' \| 'week' \| 'month' \| 'quarter' \| 'year'>` | optional | Bucket selected date dimensions (day/week/month/quarter/year) |
128+
| **sortBy** | `string` | optional | Dimension/measure name to order by |
129+
| **sortOrder** | `Enum<'asc' \| 'desc'>` | optional | Sort direction for sortBy |
130+
| **limit** | `integer` | optional | Max rows (applied after ordering) |
131+
| **stageOrder** | `string \| number \| boolean[]` | optional | Explicit category order for funnel/pyramid stages (stored values) |
132+
133+
117134
---
118135

119136
## GlobalFilter

content/docs/ui/dashboards.mdx

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,50 @@ selects `dimensions` (X / group / split) and `values` (the measures to plot):
104104
| `chartConfig` | `object` | optional | Advanced chart configuration |
105105
| `colorVariant` | `enum` | optional | KPI/card accent color |
106106
| `compareTo` | `enum \| object` | optional | Period-over-period comparison window |
107-
| `options` | `object` | optional | Additional display options |
107+
| `options` | `object` | optional | Renderer extras **plus** the query keys below |
108108
| `responsive` | `object` | optional | Responsive behavior |
109109

110+
### Widget `options`
111+
112+
`options` is an open bag: keys the renderer understands (`icon`, `columns`,
113+
`striped`, `density`, …) pass through untouched. Five keys are **declared**,
114+
because they are not presentation-only — four of them change the query the
115+
dataset compiles to:
116+
117+
| Key | Type | Effect |
118+
| :--- | :--- | :--- |
119+
| `dateGranularity` | `day \| week \| month \| quarter \| year` | Buckets this widget's selected **date** dimensions. Overrides the dataset dimension's own default for this widget only. |
120+
| `sortBy` | `string` | Orders rows by a dimension or measure **this widget selects**. |
121+
| `sortOrder` | `asc \| desc` | Direction for `sortBy` (default `asc`). |
122+
| `limit` | `number` | Max rows, applied **after** ordering. |
123+
| `stageOrder` | `(string \| number \| boolean)[]` | Explicit stage order for `funnel` / `pyramid`, as the dimension's **stored values**. Omit to use the dimension field's picklist option order. |
124+
125+
Because they are declared, a misspelling (`sortDirection`, `granularity`) is an
126+
author-time error rather than an option that reads as if it works.
127+
128+
```ts
129+
{
130+
id: 'revenue_trend',
131+
type: 'area',
132+
dataset: 'opportunity_metrics',
133+
dimensions: ['close_date'],
134+
values: ['total_amount'],
135+
// Group by month rather than by raw timestamp.
136+
options: { dateGranularity: 'month' },
137+
}
138+
```
139+
140+
Notes on behaviour:
141+
142+
- `sortBy` must name something the widget selects; the server rejects an order
143+
key it cannot resolve rather than ignoring it.
144+
- A `limit` with no `sortBy` orders by the selected dimensions first, so it
145+
truncates a reproducible window instead of an arbitrary subset.
146+
- Ordering is applied to the finished grid, so a **derived measure** is a valid
147+
`sortBy` even though no single SQL statement computes it.
148+
- A `funnel` with no declared stage order falls back to sorting by value
149+
descending.
150+
110151
## Datasets
111152

112153
Every widget binds to a **dataset** — the single semantic layer (ADR-0021).

0 commit comments

Comments
 (0)