@siyahi/ui 0.1.9-next.35 → 0.1.9-next.37

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.
Files changed (44) hide show
  1. package/DESIGN.md +80 -63
  2. package/README.md +10 -21
  3. package/THIRD_PARTY_NOTICES.md +15 -15
  4. package/agents/examples/chart-panels.tsx +0 -4
  5. package/agents/examples/metric-strip-headline.tsx +12 -0
  6. package/agents/examples/{section-cards-select.tsx → metric-strip-select.tsx} +5 -5
  7. package/agents/examples/metric-strip-trend.tsx +33 -0
  8. package/agents/examples/overview-dashboard.tsx +4 -4
  9. package/agents/examples/scatter-chart.tsx +0 -1
  10. package/agents/examples/stale-blocks.tsx +9 -9
  11. package/agents/examples/surfaces.tsx +1 -33
  12. package/agents/manifest.json +38 -53
  13. package/dist/components/registry/dashboardcn/kpi-row-card.d.ts +20 -6
  14. package/dist/components/registry/dashboardcn/kpi-row-card.js +52 -33
  15. package/dist/components/siyahi/callout.js +2 -1
  16. package/dist/components/siyahi/inline-code.d.ts +1 -1
  17. package/dist/components/siyahi/inline-code.js +1 -1
  18. package/dist/components/siyahi/page-header.js +1 -0
  19. package/dist/components/siyahi/panel-grid.d.ts +4 -6
  20. package/dist/components/siyahi/panel-grid.js +9 -12
  21. package/dist/components/siyahi/scatter-chart.d.ts +3 -3
  22. package/dist/components/siyahi/scatter-chart.js +6 -3
  23. package/dist/components/siyahi/siyahi-provider.d.ts +5 -15
  24. package/dist/components/siyahi/siyahi-provider.js +7 -17
  25. package/dist/index.d.ts +3 -4
  26. package/dist/index.js +3 -3
  27. package/dist/lib/chart-frame.d.ts +1 -1
  28. package/dist/lib/chart-frame.js +4 -2
  29. package/dist/lib/chart-series.d.ts +10 -2
  30. package/dist/lib/chart-series.js +10 -0
  31. package/dist/lib/fit-text.js +1 -1
  32. package/dist/lib/tone.d.ts +1 -1
  33. package/dist/lib/tone.js +1 -1
  34. package/package.json +2 -2
  35. package/registry.lock.json +0 -8
  36. package/styles/fallback-fonts.css +13 -13
  37. package/styles/fonts/m-plus-1-code-latin-ext-wght-normal.woff2 +0 -0
  38. package/styles/fonts/m-plus-1-code-latin-wght-normal.woff2 +0 -0
  39. package/styles/m-plus-1-code.css +21 -0
  40. package/styles/siyahi.css +166 -330
  41. package/agents/examples/section-cards-trend.tsx +0 -32
  42. package/agents/examples/section-cards.tsx +0 -48
  43. package/dist/components/registry/dashboard-01/section-cards.d.ts +0 -30
  44. package/dist/components/registry/dashboard-01/section-cards.js +0 -74
package/DESIGN.md CHANGED
@@ -10,13 +10,14 @@ component; this file says how to use them.
10
10
  Colour is placed, not spread. A page is neutral greys plus colour that carries
11
11
  a meaning:
12
12
 
13
- - **Ink indigo** is the accent: links, the selected sidebar item, the first
14
- chart series, a chart's "today" rule and an `accent` `Callout`. Buttons, badges, toggles and focus
15
- stay monochrome.
13
+ - **Terminal amber** is the accent: links, the page's eyebrow and panel
14
+ numbers, the selected sidebar item and an `accent` `Callout`. Buttons,
15
+ badges, toggles and focus stay monochrome. Charts keep their own five-hue
16
+ palette, indigo first.
16
17
  - **Green and red** mean a gain and a loss. A signed figure is `Delta`: the figure in the text colour with its
17
18
  `+` or `−`, and only a small trend icon in green or red. In plain text (labels, tooltips) write the sign; never
18
19
  colour a run of figures green and red.
19
- **Amber** means caution. None of them decorates.
20
+ **Yellow** means caution, kept apart from the amber accent. None of them decorates.
20
21
  - **Emphasis tints the whole surface.** A notice is `StatusAlert` in its tone (an
21
22
  error reads like a warning, only red); a state is `StatusBadge`; a point set
22
23
  apart is `Callout` (`neutral`, `accent`, `warning`, `positive`,
@@ -42,8 +43,8 @@ a meaning:
42
43
  fill alike. A field shows it as its own edge, 2px in the text colour; a chart
43
44
  mark as a dashed stroke, apart from a picked mark's solid one. A destructive
44
45
  control and an invalid field focus in the destructive red. Menu items show
45
- focus as their highlight. A selected
46
- toggle or pill tab fills with the foreground. A chart bar that a selection
46
+ focus as their highlight. A selected toggle or pill tab fills with the
47
+ foreground, as stock's faint grey cannot be told from the rest. A chart bar that a selection
47
48
  dims keeps its full-colour outline and fades only inside.
48
49
  - **Destructive is not loss.** `--destructive` (delete, an invalid field) is a
49
50
  deeper red than `--negative` (a loss figure), so its label reads on its own
@@ -51,57 +52,75 @@ a meaning:
51
52
  - Categories (a team, a region, a product line) stay neutral: outline badges,
52
53
  never a hue each. Ordered buckets (largest 5, next 5, rest) use steps of one
53
54
  colour, not separate hues.
54
- - **Colour marks exceptions.** The one stat tile or table row that needs a look
55
- is marked by the page: `tone: "negative"` or `"warning"` on a `SectionCards`
56
- or `MetricStrip` item, `data-tone="negative"` or `"warning"` on a `TableRow`,
55
+ - **Colour marks exceptions.** The one figure or table row that needs a look
56
+ is marked by the page: `tone: "negative"` or `"warning"` on a `MetricStrip`
57
+ item, `data-tone="negative"` or `"warning"` on a `TableRow`,
57
58
  and `getRowTone` on a `DataTableBody`, returning the tone for the row. It
58
59
  takes a faint wash of the colour over the card (7% in light, 12% in dark),
59
- and a tile or figure an outline of it. The page decides, never the sign: a falling cost is good news.
60
+ and a figure an outline of it, reaching 8px past the figure so its text
61
+ stays in line with its neighbours'. The page decides, never the sign: a falling cost is good news.
60
62
  Mark one or two; a page where every row is washed marks nothing.
61
63
 
62
64
  ## Surfaces
63
65
 
64
- `SiyahiProvider`'s `surface` sets how a data block sits on the page. The page
65
- and card colours are fixed: never tint the canvas.
66
+ A data block sits open on the page: a `Card` has no fill, no ring and no
67
+ padding, so its content sits level with the page's text. Space, not a box or a
68
+ rule, parts the blocks: 16px across and 12px down in a `PanelGrid`, 16px
69
+ between `MetricStrip` figures. A lighter box on the canvas cuts off abruptly
70
+ and spends room on its own padding, so data sits on the page. `--card` is the
71
+ page colour, so what a block's marks mix into is what lies under them. The
72
+ page colour is fixed: never tint the canvas.
66
73
 
67
- - **`ruled`** (the default, with or without a provider): ruled on white. The
68
- blocks of a `PanelGrid`, the tiles of a `SectionCards` row and the figures
69
- of a `MetricStrip` are filled with the card colour and parted by hairlines,
70
- with a rule above and below the group and none on its left and right edges.
71
- A card standing alone (a `MetricStrip`, a table's card) takes the same rules
72
- above and below itself. A short last row ends in a blank cell, ruled off
73
- like the rest. A stat tile keeps its footer's top rule and faint band. Set
74
- nothing to get it.
75
- - **`card`**: tight square cards, for a page of separate blocks, such as an
76
- index of links. Each block is filled with the card colour inside a hairline
77
- ring, with no shadow, 8px from the next in a `PanelGrid` or a row of
78
- `SectionCards`. Ask for it with `surface="card"`.
79
- - **`open`**: no fill, no lines and no padding, so a block sits level with the
80
- page's text, for pages read top to bottom.
74
+ ## Density
75
+
76
+ A page is read on a phone, a laptop and a large monitor, and each gets more of
77
+ the page, not bigger type.
78
+
79
+ - **Lay out by the room, not the device.** `PanelGrid` and the tile rows step
80
+ their columns by their own width (container queries), so a block inside a
81
+ sidebar layout or a one-file page steps the same way. Below 42rem blocks
82
+ stack; from 42rem they sit two or three across.
83
+ - **A large monitor shows more blocks, not wider ones.** From a 140rem grid a
84
+ `PanelGrid` of 2 takes a third block across, and from 180rem a grid of 2 or
85
+ 3 a fourth, when it holds that many. Text stays at its size.
86
+ - **A chart's height follows its width** unless the page fixes one: 45% of
87
+ its width, from 240px on a phone to 420px, so a chart on a wide screen
88
+ stays a chart and one on a phone keeps room for its marks. Fix a height
89
+ only where the block must line up with a neighbour.
90
+ - **Gaps are set, not invented.** Stack a page's blocks 16px apart
91
+ (`gap-4`) and its `PageSection`s 24px apart (`gap-6`), the room each
92
+ section keeps under its rule; add no padding or gap of your own around a
93
+ block.
81
94
 
82
95
  Every `PanelGrid` numbers its blocks 01, 02 before their card title, in the
83
96
  mono face and the link colour, so the text can point to one.
84
97
 
85
98
  ## Shape
86
99
 
87
- - **Square corners everywhere**: panels, cards, buttons, fields, badges,
88
- toggles, menus, bars and tracks (data bars, progress, a slider's track and
89
- thumb, a scrollbar's thumb), heatmap cells, treemap tiles and the colour
90
- chips of charts and legends alike (`--radius` is 0). Only what is round by
91
- nature stays round: an avatar, a radio, a status dot, a line's end dot, a
92
- spinner, and a signed calendar heatmap's loss day, whose shape carries its
93
- sign. The theme squares every other rounding, on any component.
94
- Never add a `rounded-*` class to a box.
95
- - **Floating surfaces lie flat.** Nothing casts a drop shadow: a menu, a
96
- list, a popover, a dialog, a sheet, a hover card and a chart's tooltip take
97
- the card's hairline for their edge, so they read as a sheet of the page.
98
- - **Joined toggles.** The items of a `ToggleGroup` sit flush and share their
99
- borders, one control; the pressed item fills with the foreground.
100
- - **A code block's copy button sits in a header row** (`CodeBlockHeader`),
101
- beside its title or alone, never floating over the code, where it would
102
- cover the end of a line. An untitled snippet takes the extra row.
100
+ - **The look is shadcn's, set by tokens.** Siyahi sets colours, fonts,
101
+ `--radius` and shadows; stock components keep the shape and states shadcn
102
+ gives them. Beyond the terminal's type (Type, below), the theme restyles a
103
+ stock component only to fix a measured problem (contrast, clipping, touch
104
+ targets, density), never for taste.
105
+ - **Square corners**: `--radius` is 0, so every corner a component takes from
106
+ the theme is square. A part shadcn rounds fully (a dot, a pill, a switch)
107
+ stays round. Never add a `rounded-*` class to a box.
108
+ - **Floating surfaces lie flat.** Nothing casts a drop shadow: every shadow
109
+ size is transparent.
103
110
  - Badges stay boxed (an outline), the primary button and the pressed toggle
104
- black (white in dark), titles in the sans face, at normal spacing.
111
+ black (white in dark).
112
+
113
+ ## Type
114
+
115
+ Siyahi reads as a terminal. The page is set in M PLUS 1 Code, a mono half a
116
+ font size wide, so a table fits its columns and a row its words on one line:
117
+ figures, labels, controls, titles and tables share one grid. Tables set it at
118
+ 13px. Text that reads as sentences, a
119
+ paragraph, a quote or a description, is set in Geist, where mono
120
+ tires the eye over a line; the theme switches it by element, so a page writes
121
+ no font classes. Labels over data (a `MetricStrip` figure's label, a table's
122
+ column heads, a sidebar group's label, a group's label in a menu) are small
123
+ capitals, muted. Never set a figure or a title in them.
105
124
 
106
125
  ## Page header
107
126
 
@@ -109,6 +128,12 @@ An app page opens on its masthead, `PageHeader`: a small mark and eyebrow in the
109
128
  mono face and link colour, the title, one muted line saying what the page is,
110
129
  the actions at the right, and a hairline under it. One per page; no hero card.
111
130
 
131
+ A page may lead with its two to four main figures as a headline, under the
132
+ masthead: `MetricStrip` with `variant="blocks"`, each figure on a solid block
133
+ (the headline orange, then the text colour, then a grey), touching, its value
134
+ large and every word in the block's own ink. One per page. It draws no
135
+ sparkline and no tone, so an exception goes in a strip below it.
136
+
112
137
  ## Words
113
138
 
114
139
  A page is read by someone who acts on its figures. Its words are plain English,
@@ -192,14 +217,9 @@ from the catalogue.
192
217
 
193
218
  ## Labels and totals
194
219
 
195
- - **Labels are small monospaced capitals**: a stat tile's label and footer
196
- lines, a `MetricStrip` label, a table's column heads, a sidebar group's
197
- label, a group's label in a menu, a select's list or the command palette,
198
- and a form field's label (muted, above the field). The components and
199
- the theme set them; never set a label in this style by hand elsewhere, and
200
- never set a figure or a title in it.
201
- - **A total row reads as a ledger's**: in `TableFooter`, one rule above it and
202
- a double rule under it in the text colour, no band.
220
+ - **Labels over data are small capitals** (Type, above). The components and
221
+ the theme set them; never set a label in this style by hand.
222
+ - **A total row** goes in `TableFooter`.
203
223
 
204
224
  ## Charts
205
225
 
@@ -235,21 +255,18 @@ from the catalogue.
235
255
  each end dot as its line finishes; bars fade in rather than grow. Reduced
236
256
  motion shows them at once.
237
257
  - **Stale data is marked by the page**: `stale` on a chart card or a
238
- `SectionCards` tile, with since when ("3 Nov"). The block greys and its
239
- chart or sparkline draws at about 65% strength, a tile's figure and badge
240
- turn muted, and a small "Stale · 3 Nov" note says so. A stale block is meant
258
+ `MetricStrip` item, with since when ("3 Nov"). The block greys and its
259
+ chart or sparkline draws at about 65% strength, a figure turns muted, and a small "Stale · 3 Nov" note says so. A stale block is meant
241
260
  to be harder to read, so its marks are exempt from the 3:1 mark bar; the
242
261
  note and the figure keep their text contrast. Never infer it from dates.
243
262
 
244
263
  ## Tables
245
264
 
246
- Tables are dense, as a ledger is: compact rows, a 1px rule in the text colour
247
- under the column heads, the first column (what the row is) in medium weight,
248
- and figures in the mono face. A figure is a cell marked `data-numeric`, which
249
- also right-aligns it (the data table marks its number columns; a plain
250
- `TableCell` or `TableHead` takes the attribute), and any `Delta` in a cell.
251
- Alignment alone is not a figure. Row hairlines stay; never stripes, never
252
- column rules.
265
+ Tables are dense: compact rows, and column heads in small muted capitals.
266
+ A number column is marked
267
+ `data-numeric`, which right-aligns it, so figures line up by their units (the
268
+ data table marks its number columns; a plain `TableCell` or `TableHead` takes
269
+ the attribute). Row hairlines stay; never stripes, never column rules.
253
270
 
254
271
  ## Forms
255
272
 
@@ -262,5 +279,5 @@ column rules.
262
279
  ## Sidebar
263
280
 
264
281
  The sidebar is parted from the page by a hairline on its page-side edge, its
265
- group labels are small monospaced capitals and its rows are compact. Its fill,
266
- icons and the current page's mark stay as shadcn draws them.
282
+ group labels are small capitals and its rows are compact. Everything else
283
+ stays as shadcn draws it.
package/README.md CHANGED
@@ -56,7 +56,7 @@ createRoot(root).render(
56
56
  );
57
57
  ```
58
58
 
59
- `preloadFonts()` loads Geist and Geist Mono with the scripts. Add `lucide-react`
59
+ `preloadFonts()` loads Geist and M PLUS 1 Code with the scripts. Add `lucide-react`
60
60
  only when your own code imports icons. Next.js compiles the stylesheet through
61
61
  `@tailwindcss/postcss` instead of the Vite plugin. To host one page as a single
62
62
  HTML file, build it with `siyahi-page` from `@siyahi/tools`.
@@ -98,26 +98,15 @@ and support one keyboard entry with arrow navigation. `WeekdayHeatmap` accepts
98
98
 
99
99
  ## Surfaces
100
100
 
101
- `SiyahiProvider` sets how data blocks sit on the page:
102
-
103
- - `surface="ruled"` (default, even outside a provider): ruled on white.
104
- `PanelGrid`, `SectionCards` and `MetricStrip` fill their blocks with the card
105
- colour and part them with hairlines, with a rule above and below each group
106
- and none on the sides; a card standing alone takes the rules above and below
107
- itself.
108
- - `surface="card"`: tight square cards, each filled inside a hairline, 8px
109
- apart, no shadow, for a page of separate blocks.
110
- - `surface="open"`: no fill, boxes or rules; card padding is removed.
111
-
112
- `DESIGN.md` has the rest of the look: square corners, mono capital labels,
113
- ledger totals, the masthead and exception tones.
114
-
115
- Nest a provider to change one section. A dialog, sheet or popover renders
116
- outside the page's provider element: `PanelGrid` and `SectionCards` carry
117
- their surface into it, but a lone `Card` there is ruled unless the popup's
118
- content sits in its own provider with an explicit surface, such as
119
- `<SiyahiProvider surface="card">`; a provider without one draws no element. Stack `PageSection` blocks with
120
- `flex flex-col gap-6`; use `PanelGrid` for blocks side by side. Categories use
101
+ Data blocks sit open on the page: a `Card` has no fill, box or rule, and no
102
+ padding, so a block's content sits level with the page's text. Space parts
103
+ the blocks: 16px across and 12px down in a `PanelGrid`. The rest of the look
104
+ is stock shadcn, set by the theme's tokens; `DESIGN.md` has the masthead and
105
+ exception tones.
106
+
107
+ Stack `PageSection` blocks with
108
+ `flex flex-col gap-6` and the blocks inside one with `gap-4`; use `PanelGrid`
109
+ for blocks side by side. Categories use
121
110
  neutral outline badges, leaving colour for meaning and chart series.
122
111
 
123
112
  ## Dark mode
@@ -8,24 +8,24 @@ file as copied; `packages/ui/registry.lock.json` lists them all and
8
8
 
9
9
  ## Copied into `@siyahi/ui`
10
10
 
11
- | What | Where in the package | Origin | Licence |
12
- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
13
- | shadcn/ui core components (installed with `shadcn add`, never edited) | `src/components/ui/*`, `src/hooks/use-mobile.ts` | https://github.com/shadcn-ui/ui | MIT, Copyright (c) 2023 shadcn |
14
- | shadcn `tailwind.css` (variants and utilities the components use) | `styles/shadcn.css` | https://github.com/shadcn-ui/ui/tree/main/packages/shadcn | MIT, Copyright (c) 2023 shadcn |
15
- | shadcn block `sidebar-07` | `src/components/registry/sidebar-07/*` | https://ui.shadcn.com/r/styles/base-vega/sidebar-07.json | MIT, Copyright (c) 2023 shadcn |
16
- | shadcn block `dashboard-01`, `SectionCards` only | `src/components/registry/dashboard-01/section-cards.tsx` | https://ui.shadcn.com/r/styles/base-vega/dashboard-01.json | MIT, Copyright (c) 2023 shadcn |
17
- | Heatmaps: calendar, weekday by hour, status timeline | `src/components/registry/heatmap/*` | https://shadcn-heatmap.pages.dev/r/calendar-heatmap.json, https://shadcn-heatmap.pages.dev/r/weekday-heatmap.json, https://shadcn-heatmap.pages.dev/r/status-heatmap.json (source: https://github.com/rutopio/shadcn-heatmap) | MIT, Copyright (c) 2026 ChingRu |
18
- | niko-table data table on TanStack Table | `src/components/registry/niko-table/*` | https://niko-table.com/r/data-table.json, https://niko-table.com/r/data-table-core.json, https://niko-table.com/r/data-table-ui.json, https://niko-table.com/r/data-table-faceted-filter.json, https://niko-table.com/r/data-table-column-sort.json, https://niko-table.com/r/data-table-search-filter.json (source: https://github.com/Semkoo/niko-table-registry) | MIT, Copyright (c) 2025 Semir N.; original work Copyright (c) 2025 WebDevSimplified |
19
- | shadcn chart blocks `chart-bar-multiple`, `chart-area-stacked`, `chart-line-multiple` | `src/components/registry/charts/*` | https://ui.shadcn.com/r/styles/new-york-v4/chart-bar-multiple.json, https://ui.shadcn.com/r/styles/new-york-v4/chart-area-stacked.json, https://ui.shadcn.com/r/styles/new-york-v4/chart-line-multiple.json | MIT, Copyright (c) 2023 shadcn |
20
- | dashboardcn ranked list (`BarList`), stacked bar (`DistributionBar`), `Sparkline` and `MetricStrip` | `src/components/registry/dashboardcn/*` | https://dashboardcn.com/r/bar-list.json, https://dashboardcn.com/r/distribution-bar.json, https://dashboardcn.com/r/sparkline.json, https://dashboardcn.com/r/kpi-row-card.json (source: https://github.com/NoahGdev/dashboardcn) | MIT, Copyright (c) 2026 dashboardcn contributors |
21
- | MiniDev copy button (`CopyButton`) | `src/components/registry/minidev/copy-button.tsx` | https://ui.minidev.pro/r/copy-button.json (source: https://github.com/amankaushik481/minidev-ui) | MIT, Copyright (c) 2026 MiniDev |
11
+ | What | Where in the package | Origin | Licence |
12
+ | --------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
13
+ | shadcn/ui core components (installed with `shadcn add`, never edited) | `src/components/ui/*`, `src/hooks/use-mobile.ts` | https://github.com/shadcn-ui/ui | MIT, Copyright (c) 2023 shadcn |
14
+ | shadcn `tailwind.css` (variants and utilities the components use) | `styles/shadcn.css` | https://github.com/shadcn-ui/ui/tree/main/packages/shadcn | MIT, Copyright (c) 2023 shadcn |
15
+ | shadcn block `sidebar-07` | `src/components/registry/sidebar-07/*` | https://ui.shadcn.com/r/styles/base-vega/sidebar-07.json | MIT, Copyright (c) 2023 shadcn |
16
+ | Heatmaps: calendar, weekday by hour, status timeline | `src/components/registry/heatmap/*` | https://shadcn-heatmap.pages.dev/r/calendar-heatmap.json, https://shadcn-heatmap.pages.dev/r/weekday-heatmap.json, https://shadcn-heatmap.pages.dev/r/status-heatmap.json (source: https://github.com/rutopio/shadcn-heatmap) | MIT, Copyright (c) 2026 ChingRu |
17
+ | niko-table data table on TanStack Table | `src/components/registry/niko-table/*` | https://niko-table.com/r/data-table.json, https://niko-table.com/r/data-table-core.json, https://niko-table.com/r/data-table-ui.json, https://niko-table.com/r/data-table-faceted-filter.json, https://niko-table.com/r/data-table-column-sort.json, https://niko-table.com/r/data-table-search-filter.json (source: https://github.com/Semkoo/niko-table-registry) | MIT, Copyright (c) 2025 Semir N.; original work Copyright (c) 2025 WebDevSimplified |
18
+ | shadcn chart blocks `chart-bar-multiple`, `chart-area-stacked`, `chart-line-multiple` | `src/components/registry/charts/*` | https://ui.shadcn.com/r/styles/new-york-v4/chart-bar-multiple.json, https://ui.shadcn.com/r/styles/new-york-v4/chart-area-stacked.json, https://ui.shadcn.com/r/styles/new-york-v4/chart-line-multiple.json | MIT, Copyright (c) 2023 shadcn |
19
+ | dashboardcn ranked list (`BarList`), stacked bar (`DistributionBar`), `Sparkline` and `MetricStrip` | `src/components/registry/dashboardcn/*` | https://dashboardcn.com/r/bar-list.json, https://dashboardcn.com/r/distribution-bar.json, https://dashboardcn.com/r/sparkline.json, https://dashboardcn.com/r/kpi-row-card.json (source: https://github.com/NoahGdev/dashboardcn) | MIT, Copyright (c) 2026 dashboardcn contributors |
20
+ | MiniDev copy button (`CopyButton`) | `src/components/registry/minidev/copy-button.tsx` | https://ui.minidev.pro/r/copy-button.json (source: https://github.com/amankaushik481/minidev-ui) | MIT, Copyright (c) 2026 MiniDev |
22
21
 
23
22
  ## Runtime dependencies with attribution terms
24
23
 
25
- | Package | Licence | Note |
26
- | --------------------------------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
27
- | `lightweight-charts` (TradingView) | Apache-2.0 | `PriceChart` keeps the library's attribution logo on by default; see https://github.com/tradingview/lightweight-charts/blob/master/NOTICE |
28
- | `@fontsource-variable/geist`, `@fontsource-variable/geist-mono` | SIL Open Font License 1.1 (fonts), MIT (packaging) | Geist by Vercel |
24
+ | Package | Licence | Note |
25
+ | ------------------------------------ | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
26
+ | `lightweight-charts` (TradingView) | Apache-2.0 | `PriceChart` keeps the library's attribution logo on by default; see https://github.com/tradingview/lightweight-charts/blob/master/NOTICE |
27
+ | `@fontsource-variable/geist` | SIL Open Font License 1.1 (fonts), MIT (packaging) | Geist by Vercel |
28
+ | `@fontsource-variable/m-plus-1-code` | SIL Open Font License 1.1 (fonts), MIT (packaging) | M PLUS 1 Code by The M+ FONTS Project Authors |
29
29
 
30
30
  Every other dependency is installed from npm under its own licence and is not
31
31
  copied into this repository.
@@ -56,7 +56,6 @@ export default function ChartPanelsExample() {
56
56
  today="Oct"
57
57
  forecastFrom="Oct"
58
58
  valueFormatter={pct}
59
- height={256}
60
59
  />
61
60
  <AreaChartCard
62
61
  title="Value by kind"
@@ -66,7 +65,6 @@ export default function ChartPanelsExample() {
66
65
  series={kinds}
67
66
  valueFormatter={money}
68
67
  yTickFormatter={moneyCompact}
69
- height={256}
70
68
  />
71
69
  <BarChartCard
72
70
  title="Money added by kind and quarter"
@@ -76,7 +74,6 @@ export default function ChartPanelsExample() {
76
74
  series={kinds}
77
75
  valueFormatter={money}
78
76
  yTickFormatter={moneyCompact}
79
- height={256}
80
77
  />
81
78
  <BarChartCard
82
79
  title="Money added by kind and quarter"
@@ -87,7 +84,6 @@ export default function ChartPanelsExample() {
87
84
  stacked
88
85
  valueFormatter={money}
89
86
  yTickFormatter={moneyCompact}
90
- height={256}
91
87
  />
92
88
  </PanelGrid>
93
89
  );
@@ -0,0 +1,12 @@
1
+ import { MetricStrip, useFormat, type MetricStripItem } from "@siyahi/ui";
2
+
3
+ export default function MetricStripHeadlineExample() {
4
+ const { money, moneyCompact } = useFormat();
5
+ // The page's headline: three figures on solid blocks. An exception goes in a strip below, not here.
6
+ const items: MetricStripItem[] = [
7
+ { label: "Net worth", value: moneyCompact(4185700), change: 0.091, note: "on the year" },
8
+ { label: "Equity share", value: "74%", note: "plan 65%" },
9
+ { label: "Cash flow this year", value: money(-61200), note: "since April" },
10
+ ];
11
+ return <MetricStrip variant="blocks" items={items} />;
12
+ }
@@ -1,4 +1,4 @@
1
- import { Delta, SectionCards, useFormat, type SectionCard } from "@siyahi/ui";
1
+ import { Delta, MetricStrip, useFormat, type MetricStripItem } from "@siyahi/ui";
2
2
  import { useState } from "react";
3
3
 
4
4
  // Each sales channel's profit this quarter and its orders; made-up figures.
@@ -9,19 +9,19 @@ const channels = [
9
9
  { label: "Marketplace", net: -61200, orders: 17 },
10
10
  ];
11
11
 
12
- export default function SectionCardsSelectExample() {
12
+ export default function MetricStripSelectExample() {
13
13
  const [scope, setScope] = useState("All");
14
14
  const { count } = useFormat();
15
- const items: SectionCard[] = channels.map((c) => ({
15
+ const items: MetricStripItem[] = channels.map((c) => ({
16
16
  label: c.label,
17
17
  value: <Delta value={c.net} format="money" />,
18
- detail: `${count(c.orders)} orders`,
18
+ note: `${count(c.orders)} orders`,
19
19
  // Nothing to show for a channel with no orders, so it cannot be picked.
20
20
  disabled: c.orders === 0,
21
21
  }));
22
22
  return (
23
23
  <div className="flex flex-col gap-3">
24
- <SectionCards items={items} selected={scope} onSelect={setScope} />
24
+ <MetricStrip items={items} selected={scope} onSelect={setScope} />
25
25
  <p className="text-sm text-muted-foreground">Showing {scope}</p>
26
26
  </div>
27
27
  );
@@ -0,0 +1,33 @@
1
+ import { MetricStrip, useFormat, type MetricStripItem } from "@siyahi/ui";
2
+
3
+ export default function MetricStripTrendExample() {
4
+ const { money, moneyCompact } = useFormat();
5
+ // trend is each figure's run, oldest first; its change's sign colours it.
6
+ const items: MetricStripItem[] = [
7
+ {
8
+ label: "Revenue",
9
+ value: money(4512300),
10
+ change: 0.031,
11
+ note: "month-end, last six months",
12
+ trend: [3820000, 3950000, 4110000, 4020000, 4380000, 4512300],
13
+ },
14
+ {
15
+ label: "Cash flow this year",
16
+ value: moneyCompact(-61200),
17
+ change: -61200,
18
+ changeFormat: "money",
19
+ note: "running total since April",
20
+ trend: [0, -8200, -14100, -30400, -52800, -61200],
21
+ // The one figure on the page that needs a look, marked by the page: a falling cost would not be.
22
+ tone: "negative",
23
+ },
24
+ {
25
+ label: "Gift cards this year",
26
+ value: moneyCompact(38400),
27
+ change: 0.18,
28
+ note: "sold each month",
29
+ trend: [4100, 0, 12800, 3300, 9900, 8300],
30
+ },
31
+ ];
32
+ return <MetricStrip items={items} />;
33
+ }
@@ -26,7 +26,7 @@ import {
26
26
  import { DownloadIcon, LightbulbIcon, PlusIcon } from "lucide-react";
27
27
  import { useState } from "react";
28
28
  import ChartArea from "./chart-area";
29
- import SectionCardsTrend from "./section-cards-trend";
29
+ import MetricStripTrend from "./metric-strip-trend";
30
30
 
31
31
  interface Holding {
32
32
  name: string;
@@ -119,8 +119,8 @@ function Holdings({ rows }: { rows: Holding[] }) {
119
119
  );
120
120
  }
121
121
 
122
- // An app page on the default, ruled surface: masthead, controls, stat tiles, a chart and a table in a PanelGrid, and
123
- // the takeaway. It sets no surface: ruled on white is what a page gets.
122
+ // An app page on the default, open surface: masthead, controls, stat tiles, a chart and a table in a PanelGrid, and
123
+ // the takeaway. It sets no surface: blocks on the page with space between them is what a page gets.
124
124
  export default function OverviewDashboard() {
125
125
  const [query, setQuery] = useState("");
126
126
  const shown = holdings.filter((row) => row.name.toLowerCase().includes(query.trim().toLowerCase()));
@@ -166,7 +166,7 @@ export default function OverviewDashboard() {
166
166
  </a>
167
167
  </p>
168
168
  </div>
169
- <SectionCardsTrend />
169
+ <MetricStripTrend />
170
170
  <PanelGrid>
171
171
  <ChartArea />
172
172
  <Holdings rows={shown} />
@@ -43,7 +43,6 @@ export default function ScatterChartExample() {
43
43
  description="Across is the store's share of sales, up its growth on last year. Log spreads out the small stores; Linear shows how far ahead the largest are."
44
44
  action={<Badge variant="outline">This month</Badge>}
45
45
  points={stores}
46
- height={360}
47
46
  xLabel="Share of sales"
48
47
  yLabel="Growth"
49
48
  // Log is selected first; the buttons in the header let the reader switch.
@@ -1,4 +1,4 @@
1
- import { AreaChartCard, Delta, SectionCards, Sparkline, useFormat, type SectionCard } from "@siyahi/ui";
1
+ import { AreaChartCard, MetricStrip, useFormat, type MetricStripItem } from "@siyahi/ui";
2
2
 
3
3
  const value = [
4
4
  { month: "May", equity: 2150000, debt: 600000, gold: 320000, intl: 390000, cash: 150000 },
@@ -20,26 +20,26 @@ const kinds = [
20
20
  // loses its colour and says since when. The page decides; nothing is inferred from dates.
21
21
  export default function StaleBlocksExample() {
22
22
  const { money, moneyCompact } = useFormat();
23
- const tiles: SectionCard[] = [
23
+ const figures: MetricStripItem[] = [
24
24
  {
25
25
  label: "Revenue",
26
26
  value: money(4512300),
27
- badge: <Delta value={0.031} />,
28
- trend: <Sparkline data={[3820000, 3950000, 4110000, 4020000, 4380000, 4512300]} />,
29
- detail: "Month-end, last six months",
27
+ change: 0.031,
28
+ note: "month-end, last six months",
29
+ trend: [3820000, 3950000, 4110000, 4020000, 4380000, 4512300],
30
30
  },
31
31
  {
32
32
  label: "Gift cards this year",
33
33
  value: moneyCompact(38400),
34
- badge: <Delta value={0.18} />,
35
- trend: <Sparkline data={[4100, 0, 12800, 3300, 9900, 8300]} variant="line" curve="linear" />,
36
- detail: "Sold each month",
34
+ change: 0.18,
35
+ note: "sold each month",
36
+ trend: [4100, 0, 12800, 3300, 9900, 8300],
37
37
  stale: "3 Nov",
38
38
  },
39
39
  ];
40
40
  return (
41
41
  <div className="flex flex-col gap-6">
42
- <SectionCards items={tiles} />
42
+ <MetricStrip items={figures} />
43
43
  <AreaChartCard
44
44
  title="Value by kind"
45
45
  description="Month-end value of each kind of holding"
@@ -7,20 +7,15 @@ import {
7
7
  CardTitle,
8
8
  MetricStrip,
9
9
  PanelGrid,
10
- SiyahiProvider,
11
10
  Table,
12
11
  TableBody,
13
12
  TableCell,
14
13
  TableHead,
15
14
  TableHeader,
16
15
  TableRow,
17
- ToggleGroup,
18
- ToggleGroupItem,
19
16
  useFormat,
20
17
  type MetricStripItem,
21
- type Surface,
22
18
  } from "@siyahi/ui";
23
- import { useState } from "react";
24
19
 
25
20
  const orders = [
26
21
  { hour: 9, orders: 42 },
@@ -38,7 +33,7 @@ const products = [
38
33
  { product: "Bookshelf", revenue: 166000 },
39
34
  ];
40
35
 
41
- function Dashboard() {
36
+ export default function SurfacesExample() {
42
37
  const { money, moneyCompact, pct } = useFormat();
43
38
  const kpis: MetricStripItem[] = [
44
39
  { label: "Revenue", value: money(4512300), change: 0.031 },
@@ -87,30 +82,3 @@ function Dashboard() {
87
82
  </div>
88
83
  );
89
84
  }
90
-
91
- export default function SurfacesExample() {
92
- const [surface, setSurface] = useState<Surface>("ruled");
93
- return (
94
- <div className="flex flex-col gap-4">
95
- <ToggleGroup
96
- value={[surface]}
97
- onValueChange={([next]) => {
98
- // Pressing the selected surface again would leave none selected; keep it.
99
- if (next) setSurface(next as Surface);
100
- }}
101
- variant="outline"
102
- size="sm"
103
- aria-label="Surface"
104
- >
105
- {/* The default first. */}
106
- <ToggleGroupItem value="ruled">Ruled</ToggleGroupItem>
107
- <ToggleGroupItem value="card">Card</ToggleGroupItem>
108
- <ToggleGroupItem value="open">Open</ToggleGroupItem>
109
- </ToggleGroup>
110
- {/* A nested provider sets the surface for its part of the page. */}
111
- <SiyahiProvider surface={surface}>
112
- <Dashboard />
113
- </SiyahiProvider>
114
- </div>
115
- );
116
- }