@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.
- package/DESIGN.md +80 -63
- package/README.md +10 -21
- package/THIRD_PARTY_NOTICES.md +15 -15
- package/agents/examples/chart-panels.tsx +0 -4
- package/agents/examples/metric-strip-headline.tsx +12 -0
- package/agents/examples/{section-cards-select.tsx → metric-strip-select.tsx} +5 -5
- package/agents/examples/metric-strip-trend.tsx +33 -0
- package/agents/examples/overview-dashboard.tsx +4 -4
- package/agents/examples/scatter-chart.tsx +0 -1
- package/agents/examples/stale-blocks.tsx +9 -9
- package/agents/examples/surfaces.tsx +1 -33
- package/agents/manifest.json +38 -53
- package/dist/components/registry/dashboardcn/kpi-row-card.d.ts +20 -6
- package/dist/components/registry/dashboardcn/kpi-row-card.js +52 -33
- package/dist/components/siyahi/callout.js +2 -1
- package/dist/components/siyahi/inline-code.d.ts +1 -1
- package/dist/components/siyahi/inline-code.js +1 -1
- package/dist/components/siyahi/page-header.js +1 -0
- package/dist/components/siyahi/panel-grid.d.ts +4 -6
- package/dist/components/siyahi/panel-grid.js +9 -12
- package/dist/components/siyahi/scatter-chart.d.ts +3 -3
- package/dist/components/siyahi/scatter-chart.js +6 -3
- package/dist/components/siyahi/siyahi-provider.d.ts +5 -15
- package/dist/components/siyahi/siyahi-provider.js +7 -17
- package/dist/index.d.ts +3 -4
- package/dist/index.js +3 -3
- package/dist/lib/chart-frame.d.ts +1 -1
- package/dist/lib/chart-frame.js +4 -2
- package/dist/lib/chart-series.d.ts +10 -2
- package/dist/lib/chart-series.js +10 -0
- package/dist/lib/fit-text.js +1 -1
- package/dist/lib/tone.d.ts +1 -1
- package/dist/lib/tone.js +1 -1
- package/package.json +2 -2
- package/registry.lock.json +0 -8
- package/styles/fallback-fonts.css +13 -13
- package/styles/fonts/m-plus-1-code-latin-ext-wght-normal.woff2 +0 -0
- package/styles/fonts/m-plus-1-code-latin-wght-normal.woff2 +0 -0
- package/styles/m-plus-1-code.css +21 -0
- package/styles/siyahi.css +166 -330
- package/agents/examples/section-cards-trend.tsx +0 -32
- package/agents/examples/section-cards.tsx +0 -48
- package/dist/components/registry/dashboard-01/section-cards.d.ts +0 -30
- 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
|
-
- **
|
|
14
|
-
|
|
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
|
-
**
|
|
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
|
-
|
|
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
|
|
55
|
-
is marked by the page: `tone: "negative"` or `"warning"` on a `
|
|
56
|
-
|
|
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
|
|
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
|
-
|
|
65
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
|
|
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
|
-
- **
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
Never add a `rounded-*` class to a box.
|
|
95
|
-
- **Floating surfaces lie flat.** Nothing casts a drop shadow:
|
|
96
|
-
|
|
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)
|
|
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
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
`
|
|
239
|
-
chart or sparkline draws at about 65% strength, a
|
|
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
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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
|
|
266
|
-
|
|
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
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
- `
|
|
109
|
-
|
|
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
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -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
|
|
12
|
-
| --------------------------------------------------------------------------------------------------- |
|
|
13
|
-
| shadcn/ui core components (installed with `shadcn add`, never edited) | `src/components/ui/*`, `src/hooks/use-mobile.ts`
|
|
14
|
-
| shadcn `tailwind.css` (variants and utilities the components use) | `styles/shadcn.css`
|
|
15
|
-
| shadcn block `sidebar-07` | `src/components/registry/sidebar-07/*`
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
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
|
|
26
|
-
|
|
|
27
|
-
| `lightweight-charts` (TradingView)
|
|
28
|
-
| `@fontsource-variable/geist
|
|
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,
|
|
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
|
|
12
|
+
export default function MetricStripSelectExample() {
|
|
13
13
|
const [scope, setScope] = useState("All");
|
|
14
14
|
const { count } = useFormat();
|
|
15
|
-
const items:
|
|
15
|
+
const items: MetricStripItem[] = channels.map((c) => ({
|
|
16
16
|
label: c.label,
|
|
17
17
|
value: <Delta value={c.net} format="money" />,
|
|
18
|
-
|
|
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
|
-
<
|
|
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
|
|
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,
|
|
123
|
-
// the takeaway. It sets no surface:
|
|
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
|
-
<
|
|
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,
|
|
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
|
|
23
|
+
const figures: MetricStripItem[] = [
|
|
24
24
|
{
|
|
25
25
|
label: "Revenue",
|
|
26
26
|
value: money(4512300),
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
<
|
|
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
|
|
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
|
-
}
|