@siyahi/ui 0.1.9-next.36 → 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 +53 -52
- package/README.md +7 -16
- package/THIRD_PARTY_NOTICES.md +5 -4
- package/agents/examples/metric-strip-headline.tsx +12 -0
- package/agents/examples/surfaces.tsx +1 -32
- package/agents/manifest.json +15 -10
- package/dist/components/registry/dashboardcn/kpi-row-card.d.ts +7 -1
- package/dist/components/registry/dashboardcn/kpi-row-card.js +8 -6
- 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 +2 -3
- package/dist/components/siyahi/panel-grid.js +3 -7
- package/dist/components/siyahi/scatter-chart.js +1 -1
- package/dist/components/siyahi/siyahi-provider.d.ts +5 -14
- package/dist/components/siyahi/siyahi-provider.js +7 -17
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/lib/chart-frame.js +1 -1
- 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/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 +136 -297
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
|
|
@@ -62,19 +63,13 @@ a meaning:
|
|
|
62
63
|
|
|
63
64
|
## Surfaces
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
cuts off abruptly and spends room on its own padding, so data sits on the
|
|
73
|
-
page. Set nothing to get it.
|
|
74
|
-
- **`card`**: tight square cards, for a page of separate blocks, such as an
|
|
75
|
-
index of links. Each block is filled with the card colour inside a hairline
|
|
76
|
-
ring, with no shadow, 8px from the next in a `PanelGrid`. Ask for it with
|
|
77
|
-
`surface="card"`.
|
|
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.
|
|
78
73
|
|
|
79
74
|
## Density
|
|
80
75
|
|
|
@@ -102,24 +97,30 @@ mono face and the link colour, so the text can point to one.
|
|
|
102
97
|
|
|
103
98
|
## Shape
|
|
104
99
|
|
|
105
|
-
- **
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
Never add a `rounded-*` class to a box.
|
|
113
|
-
- **Floating surfaces lie flat.** Nothing casts a drop shadow:
|
|
114
|
-
|
|
115
|
-
the card's hairline for their edge, so they read as a sheet of the page.
|
|
116
|
-
- **Joined toggles.** The items of a `ToggleGroup` sit flush and share their
|
|
117
|
-
borders, one control; the pressed item fills with the foreground.
|
|
118
|
-
- **A code block's copy button sits in a header row** (`CodeBlockHeader`),
|
|
119
|
-
beside its title or alone, never floating over the code, where it would
|
|
120
|
-
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.
|
|
121
110
|
- Badges stay boxed (an outline), the primary button and the pressed toggle
|
|
122
|
-
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.
|
|
123
124
|
|
|
124
125
|
## Page header
|
|
125
126
|
|
|
@@ -127,6 +128,12 @@ An app page opens on its masthead, `PageHeader`: a small mark and eyebrow in the
|
|
|
127
128
|
mono face and link colour, the title, one muted line saying what the page is,
|
|
128
129
|
the actions at the right, and a hairline under it. One per page; no hero card.
|
|
129
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
|
+
|
|
130
137
|
## Words
|
|
131
138
|
|
|
132
139
|
A page is read by someone who acts on its figures. Its words are plain English,
|
|
@@ -210,13 +217,9 @@ from the catalogue.
|
|
|
210
217
|
|
|
211
218
|
## Labels and totals
|
|
212
219
|
|
|
213
|
-
- **Labels are small
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
the theme set them; never set a label in this style by hand elsewhere, and
|
|
217
|
-
never set a figure or a title in it.
|
|
218
|
-
- **A total row reads as a ledger's**: in `TableFooter`, one rule above it and
|
|
219
|
-
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`.
|
|
220
223
|
|
|
221
224
|
## Charts
|
|
222
225
|
|
|
@@ -259,13 +262,11 @@ from the catalogue.
|
|
|
259
262
|
|
|
260
263
|
## Tables
|
|
261
264
|
|
|
262
|
-
Tables are dense
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
Alignment alone is not a figure. Row hairlines stay; never stripes, never
|
|
268
|
-
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.
|
|
269
270
|
|
|
270
271
|
## Forms
|
|
271
272
|
|
|
@@ -278,5 +279,5 @@ column rules.
|
|
|
278
279
|
## Sidebar
|
|
279
280
|
|
|
280
281
|
The sidebar is parted from the page by a hairline on its page-side edge, its
|
|
281
|
-
group labels are small
|
|
282
|
-
|
|
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,22 +98,13 @@ and support one keyboard entry with arrow navigation. `WeekdayHeatmap` accepts
|
|
|
98
98
|
|
|
99
99
|
## Surfaces
|
|
100
100
|
|
|
101
|
-
|
|
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.
|
|
102
106
|
|
|
103
|
-
|
|
104
|
-
and no card padding, so a block's content sits level with the page's text.
|
|
105
|
-
Space parts the blocks: 24px across and 16px down in a `PanelGrid`.
|
|
106
|
-
- `surface="card"`: tight square cards, each filled inside a hairline, 8px
|
|
107
|
-
apart, no shadow, for a page of separate blocks.
|
|
108
|
-
|
|
109
|
-
`DESIGN.md` has the rest of the look: square corners, mono capital labels,
|
|
110
|
-
ledger totals, the masthead and exception tones.
|
|
111
|
-
|
|
112
|
-
Nest a provider to change one section. A dialog, sheet or popover renders
|
|
113
|
-
outside the page's provider element: `PanelGrid` carries
|
|
114
|
-
their surface into it, but a lone `Card` there is open unless the popup's
|
|
115
|
-
content sits in its own provider with an explicit surface, such as
|
|
116
|
-
`<SiyahiProvider surface="card">`; a provider without one draws no element. Stack `PageSection` blocks with
|
|
107
|
+
Stack `PageSection` blocks with
|
|
117
108
|
`flex flex-col gap-6` and the blocks inside one with `gap-4`; use `PanelGrid`
|
|
118
109
|
for blocks side by side. Categories use
|
|
119
110
|
neutral outline badges, leaving colour for meaning and chart series.
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -21,10 +21,11 @@ file as copied; `packages/ui/registry.lock.json` lists them all and
|
|
|
21
21
|
|
|
22
22
|
## Runtime dependencies with attribution terms
|
|
23
23
|
|
|
24
|
-
| Package
|
|
25
|
-
|
|
|
26
|
-
| `lightweight-charts` (TradingView)
|
|
27
|
-
| `@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 |
|
|
28
29
|
|
|
29
30
|
Every other dependency is installed from npm under its own licence and is not
|
|
30
31
|
copied into this repository.
|
|
@@ -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
|
+
}
|
|
@@ -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,29 +82,3 @@ function Dashboard() {
|
|
|
87
82
|
</div>
|
|
88
83
|
);
|
|
89
84
|
}
|
|
90
|
-
|
|
91
|
-
export default function SurfacesExample() {
|
|
92
|
-
const [surface, setSurface] = useState<Surface>("open");
|
|
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="open">Open</ToggleGroupItem>
|
|
107
|
-
<ToggleGroupItem value="card">Card</ToggleGroupItem>
|
|
108
|
-
</ToggleGroup>
|
|
109
|
-
{/* A nested provider sets the surface for its part of the page. */}
|
|
110
|
-
<SiyahiProvider surface={surface}>
|
|
111
|
-
<Dashboard />
|
|
112
|
-
</SiyahiProvider>
|
|
113
|
-
</div>
|
|
114
|
-
);
|
|
115
|
-
}
|
package/agents/manifest.json
CHANGED
|
@@ -106,6 +106,14 @@
|
|
|
106
106
|
"MetricStrip"
|
|
107
107
|
]
|
|
108
108
|
},
|
|
109
|
+
{
|
|
110
|
+
"need": "The two to four figures a page leads with, set large at its top",
|
|
111
|
+
"guidance": "`MetricStrip` with `variant=\"blocks\"`, once per page, under the `PageHeader`",
|
|
112
|
+
"components": [
|
|
113
|
+
"MetricStrip",
|
|
114
|
+
"PageHeader"
|
|
115
|
+
]
|
|
116
|
+
},
|
|
109
117
|
{
|
|
110
118
|
"need": "A run of values beside a figure, in a tile, a strip or a table cell",
|
|
111
119
|
"guidance": "`Sparkline`; in a strip, `MetricStrip`'s `trend`",
|
|
@@ -280,13 +288,6 @@
|
|
|
280
288
|
"PanelGrid"
|
|
281
289
|
]
|
|
282
290
|
},
|
|
283
|
-
{
|
|
284
|
-
"need": "Separate square cards instead of the default open blocks, for a page or a part of one",
|
|
285
|
-
"guidance": "`SiyahiProvider` with `surface=\"card\"`",
|
|
286
|
-
"components": [
|
|
287
|
-
"SiyahiProvider"
|
|
288
|
-
]
|
|
289
|
-
},
|
|
290
291
|
{
|
|
291
292
|
"need": "A forecast stretch after the latest actual figure, or a marker for today",
|
|
292
293
|
"guidance": "`LineChartCard` or `AreaChartCard` with `forecastFrom` and `today` set to x values",
|
|
@@ -1018,6 +1019,13 @@
|
|
|
1018
1019
|
"LocalTime"
|
|
1019
1020
|
]
|
|
1020
1021
|
},
|
|
1022
|
+
{
|
|
1023
|
+
"file": "agents/examples/metric-strip-headline.tsx",
|
|
1024
|
+
"components": [
|
|
1025
|
+
"MetricStrip",
|
|
1026
|
+
"useFormat"
|
|
1027
|
+
]
|
|
1028
|
+
},
|
|
1021
1029
|
{
|
|
1022
1030
|
"file": "agents/examples/metric-strip-select.tsx",
|
|
1023
1031
|
"components": [
|
|
@@ -1276,15 +1284,12 @@
|
|
|
1276
1284
|
"CardTitle",
|
|
1277
1285
|
"MetricStrip",
|
|
1278
1286
|
"PanelGrid",
|
|
1279
|
-
"SiyahiProvider",
|
|
1280
1287
|
"Table",
|
|
1281
1288
|
"TableBody",
|
|
1282
1289
|
"TableCell",
|
|
1283
1290
|
"TableHead",
|
|
1284
1291
|
"TableHeader",
|
|
1285
1292
|
"TableRow",
|
|
1286
|
-
"ToggleGroup",
|
|
1287
|
-
"ToggleGroupItem",
|
|
1288
1293
|
"useFormat"
|
|
1289
1294
|
]
|
|
1290
1295
|
},
|
|
@@ -32,8 +32,14 @@ export interface MetricStripProps extends Omit<React$1.ComponentProps<typeof Car
|
|
|
32
32
|
selected?: string | undefined;
|
|
33
33
|
/** Makes each figure one button, so keep figure content non-interactive; gets the label of the figure picked. */
|
|
34
34
|
onSelect?: ((label: string) => void) | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* "strip", the default: figures on the page with their sparklines. "blocks": the page's headline, two to four
|
|
37
|
+
* figures each on a solid block with a large value; it draws no sparkline and no tone, so mark an exception in a
|
|
38
|
+
* strip below it. One per page.
|
|
39
|
+
*/
|
|
40
|
+
variant?: "strip" | "blocks" | undefined;
|
|
35
41
|
}
|
|
36
42
|
/** A row of figures, each with its change and recent run, optionally a picker that scopes the page. */
|
|
37
|
-
declare function MetricStrip({ title, description, action, items, footer, selected, onSelect, className, ...props }: MetricStripProps): React$1.JSX.Element;
|
|
43
|
+
declare function MetricStrip({ title, description, action, items, footer, selected, onSelect, variant, className, ...props }: MetricStripProps): React$1.JSX.Element;
|
|
38
44
|
//#endregion
|
|
39
45
|
export { MetricStrip };
|
|
@@ -23,8 +23,9 @@ function trendColor(change) {
|
|
|
23
23
|
return "var(--muted-foreground)";
|
|
24
24
|
}
|
|
25
25
|
/** A row of figures, each with its change and recent run, optionally a picker that scopes the page. */
|
|
26
|
-
function MetricStrip({ title, description, action, items, footer, selected, onSelect, className, ...props }) {
|
|
26
|
+
function MetricStrip({ title, description, action, items, footer, selected, onSelect, variant = "strip", className, ...props }) {
|
|
27
27
|
const columns = COLUMNS[Math.min(items.length, 8)] ?? COLUMNS[8];
|
|
28
|
+
const blocks = variant === "blocks";
|
|
28
29
|
return /* @__PURE__ */ jsxs(Card, {
|
|
29
30
|
className: cn("gap-4", className),
|
|
30
31
|
...props,
|
|
@@ -36,15 +37,16 @@ function MetricStrip({ title, description, action, items, footer, selected, onSe
|
|
|
36
37
|
] }),
|
|
37
38
|
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx("div", {
|
|
38
39
|
"data-slot": "metric-strip",
|
|
40
|
+
"data-variant": variant,
|
|
39
41
|
className: "@container/strip",
|
|
40
42
|
children: /* @__PURE__ */ jsx("div", {
|
|
41
|
-
className: cn("grid grid-cols-1 gap-
|
|
43
|
+
className: cn("grid grid-cols-1", blocks ? "gap-0" : "gap-4", columns),
|
|
42
44
|
children: items.map((item) => /* @__PURE__ */ jsxs("div", {
|
|
43
45
|
"data-slot": "metric-strip-item",
|
|
44
|
-
"data-tone": item.tone,
|
|
46
|
+
"data-tone": blocks ? void 0 : item.tone,
|
|
45
47
|
"data-stale": item.stale ? "" : void 0,
|
|
46
48
|
"data-picked": onSelect && item.label === selected ? "" : void 0,
|
|
47
|
-
className: cn("relative
|
|
49
|
+
className: cn("relative grid min-w-0 grid-rows-subgrid gap-y-1", blocks ? "row-span-3 p-4" : "row-span-4", onSelect && item.disabled && "opacity-60"),
|
|
48
50
|
children: [
|
|
49
51
|
onSelect && /* @__PURE__ */ jsx("button", {
|
|
50
52
|
type: "button",
|
|
@@ -61,7 +63,7 @@ function MetricStrip({ title, description, action, items, footer, selected, onSe
|
|
|
61
63
|
}),
|
|
62
64
|
/* @__PURE__ */ jsx("div", {
|
|
63
65
|
"data-slot": "metric-strip-value",
|
|
64
|
-
className: "text-
|
|
66
|
+
className: cn("font-semibold tabular-nums", blocks ? "mt-2 text-4xl leading-none tracking-tighter" : "text-lg tracking-tight"),
|
|
65
67
|
children: item.value
|
|
66
68
|
}),
|
|
67
69
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -78,7 +80,7 @@ function MetricStrip({ title, description, action, items, footer, selected, onSe
|
|
|
78
80
|
item.stale && /* @__PURE__ */ jsx(StaleNote, { since: item.stale })
|
|
79
81
|
]
|
|
80
82
|
}),
|
|
81
|
-
item.trend && item.trend.length > 1 ? /* @__PURE__ */ jsx(Sparkline, {
|
|
83
|
+
blocks ? null : item.trend && item.trend.length > 1 ? /* @__PURE__ */ jsx(Sparkline, {
|
|
82
84
|
data: item.trend,
|
|
83
85
|
variant: "line",
|
|
84
86
|
color: trendColor(item.change),
|
|
@@ -21,9 +21,10 @@ function Callout({ tone = "neutral", icon, title, className, children, ...props
|
|
|
21
21
|
}), /* @__PURE__ */ jsxs("div", {
|
|
22
22
|
className: "flex min-w-0 flex-col gap-1",
|
|
23
23
|
children: [title && /* @__PURE__ */ jsx("p", {
|
|
24
|
-
className: "font-medium",
|
|
24
|
+
className: "font-heading font-medium",
|
|
25
25
|
children: title
|
|
26
26
|
}), /* @__PURE__ */ jsx("div", {
|
|
27
|
+
"data-slot": "callout-description",
|
|
27
28
|
className: "text-pretty text-muted-foreground [&_strong]:text-foreground",
|
|
28
29
|
children
|
|
29
30
|
})]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
//#region src/components/siyahi/inline-code.d.ts
|
|
3
|
-
/** A command, file name or identifier inside prose, in
|
|
3
|
+
/** A command, file name or identifier inside prose, in the mono face on a muted chip, at the size of the text around it. */
|
|
4
4
|
export declare function InlineCode({ children }: {
|
|
5
5
|
children: ReactNode;
|
|
6
6
|
}): import("react").JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
//#region src/components/siyahi/inline-code.tsx
|
|
3
|
-
/** A command, file name or identifier inside prose, in
|
|
3
|
+
/** A command, file name or identifier inside prose, in the mono face on a muted chip, at the size of the text around it. */
|
|
4
4
|
function InlineCode({ children }) {
|
|
5
5
|
return /* @__PURE__ */ jsx("code", {
|
|
6
6
|
className: "rounded-sm bg-muted px-1 font-mono",
|
|
@@ -25,6 +25,7 @@ function PageHeader({ eyebrow, title, lead, detail, actions, mark }) {
|
|
|
25
25
|
children: title
|
|
26
26
|
}),
|
|
27
27
|
(lead || detail) && /* @__PURE__ */ jsxs("div", {
|
|
28
|
+
"data-slot": "page-header-description",
|
|
28
29
|
className: "text-sm text-pretty text-muted-foreground",
|
|
29
30
|
children: [
|
|
30
31
|
lead,
|
|
@@ -17,9 +17,8 @@ export interface PanelGridProps {
|
|
|
17
17
|
className?: string | undefined;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* Data blocks side by side: chart cards, tables, a MetricStrip.
|
|
21
|
-
*
|
|
22
|
-
* theme numbers each block's card title 01, 02.
|
|
20
|
+
* Data blocks side by side: chart cards, tables, a MetricStrip. Space parts the blocks, 16px across and 12px down,
|
|
21
|
+
* with no box and no rule. The theme numbers each block's card title 01, 02.
|
|
23
22
|
*/
|
|
24
23
|
export declare function PanelGrid({ columns, children, className }: PanelGridProps): import("react").JSX.Element;
|
|
25
24
|
//#endregion
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { useSurface } from "./siyahi-provider.js";
|
|
2
1
|
import { cn } from "cn";
|
|
3
2
|
import { jsx } from "react/jsx-runtime";
|
|
4
3
|
import { Children } from "react";
|
|
@@ -12,20 +11,17 @@ const COLUMNS = {
|
|
|
12
11
|
const WIDE_THREE = "@min-[140rem]/panels:grid-cols-3";
|
|
13
12
|
const WIDE_FOUR = "@min-[180rem]/panels:grid-cols-4";
|
|
14
13
|
/**
|
|
15
|
-
* Data blocks side by side: chart cards, tables, a MetricStrip.
|
|
16
|
-
*
|
|
17
|
-
* theme numbers each block's card title 01, 02.
|
|
14
|
+
* Data blocks side by side: chart cards, tables, a MetricStrip. Space parts the blocks, 16px across and 12px down,
|
|
15
|
+
* with no box and no rule. The theme numbers each block's card title 01, 02.
|
|
18
16
|
*/
|
|
19
17
|
function PanelGrid({ columns = 2, children, className }) {
|
|
20
|
-
const surface = useSurface();
|
|
21
18
|
const blocks = Children.toArray(children).length;
|
|
22
19
|
const wide = cn(columns === 2 && blocks >= 3 && WIDE_THREE, (columns === 2 || columns === 3) && blocks >= 4 && WIDE_FOUR);
|
|
23
20
|
return /* @__PURE__ */ jsx("div", {
|
|
24
21
|
"data-slot": "panel-grid",
|
|
25
|
-
"data-surface": surface,
|
|
26
22
|
className: cn("@container/panels", className),
|
|
27
23
|
children: /* @__PURE__ */ jsx("div", {
|
|
28
|
-
className: cn("grid grid-cols-1
|
|
24
|
+
className: cn("grid grid-cols-1 gap-x-4 gap-y-3", COLUMNS[columns], wide),
|
|
29
25
|
children: Children.map(children, (child) => /* @__PURE__ */ jsx("div", {
|
|
30
26
|
"data-slot": "panel",
|
|
31
27
|
className: "min-w-0",
|
|
@@ -19,7 +19,7 @@ const NAME_BAND = 42;
|
|
|
19
19
|
const TICK = { className: "fill-muted-foreground font-mono" };
|
|
20
20
|
const AXIS_TITLE = "fill-muted-foreground text-xs";
|
|
21
21
|
const keyOf = (point) => point.key ?? point.name;
|
|
22
|
-
const MONO_WIDTH =
|
|
22
|
+
const MONO_WIDTH = 6;
|
|
23
23
|
/** Two measures per item as dots, such as size against growth, with the leading names beside their dots. */
|
|
24
24
|
function ScatterChartCard({ title, description, action, points, height: fixedHeight, xLabel, yLabel, xScale = "linear", xScaleToggle = false, yScale = "linear", yScaleToggle = false, xFormatter, yFormatter, labels = 12, details, selected = null, onSelect, footer, quadrants, sizeLabel = "Size", sizeFormatter }) {
|
|
25
25
|
const { numberLocale } = useLocale();
|
|
@@ -2,24 +2,15 @@ import { Optional } from "../../lib/optional.js";
|
|
|
2
2
|
import { SiyahiLocale } from "../../lib/locale.js";
|
|
3
3
|
import { ReactNode } from "react";
|
|
4
4
|
//#region src/components/siyahi/siyahi-provider.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* How a data block sits on the page. "open", the default: no fill, no lines and no padding, the block's content level
|
|
7
|
-
* with the page's text and parted from the next by space. "card": a filled square card in a hairline ring, 8px from
|
|
8
|
-
* the next, for a page of separate blocks.
|
|
9
|
-
*/
|
|
10
|
-
export type Surface = "open" | "card";
|
|
11
5
|
export interface SiyahiProviderProps {
|
|
12
6
|
/** Any setting left out keeps its default: en-IN, INR, Asia/Kolkata. */
|
|
13
7
|
locale?: Optional<SiyahiLocale> | undefined;
|
|
14
|
-
/**
|
|
15
|
-
* Set it on a nested provider for one part of a page. Left out, a provider keeps the surface around it, so a
|
|
16
|
-
* provider that only changes the locale changes nothing else; the outermost default is "open".
|
|
17
|
-
*/
|
|
18
|
-
surface?: Surface | undefined;
|
|
19
8
|
children: ReactNode;
|
|
20
9
|
}
|
|
21
|
-
/**
|
|
22
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Wrap the app once. Carries the locale and the tooltip provider shadcn asks for, and draws no element of its own, so
|
|
12
|
+
* a provider that changes the locale for a table's rows can sit inside a <tbody>.
|
|
13
|
+
*/
|
|
14
|
+
export declare function SiyahiProvider({ locale, children }: SiyahiProviderProps): import("react").JSX.Element;
|
|
23
15
|
export declare function useLocale(): SiyahiLocale;
|
|
24
|
-
export declare function useSurface(): Surface;
|
|
25
16
|
//#endregion
|
|
@@ -4,9 +4,11 @@ import { jsx } from "react/jsx-runtime";
|
|
|
4
4
|
import { createContext, use, useMemo } from "react";
|
|
5
5
|
//#region src/components/siyahi/siyahi-provider.tsx
|
|
6
6
|
const LocaleContext = createContext(defaultLocale);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Wrap the app once. Carries the locale and the tooltip provider shadcn asks for, and draws no element of its own, so
|
|
9
|
+
* a provider that changes the locale for a table's rows can sit inside a <tbody>.
|
|
10
|
+
*/
|
|
11
|
+
function SiyahiProvider({ locale, children }) {
|
|
10
12
|
const { numberLocale = defaultLocale.numberLocale, currency = defaultLocale.currency, timeZone = defaultLocale.timeZone } = locale ?? {};
|
|
11
13
|
const value = useMemo(() => ({
|
|
12
14
|
numberLocale,
|
|
@@ -17,25 +19,13 @@ function SiyahiProvider({ locale, surface, children }) {
|
|
|
17
19
|
currency,
|
|
18
20
|
timeZone
|
|
19
21
|
]);
|
|
20
|
-
const around = use(SurfaceContext);
|
|
21
22
|
return /* @__PURE__ */ jsx(LocaleContext, {
|
|
22
23
|
value,
|
|
23
|
-
children: /* @__PURE__ */ jsx(
|
|
24
|
-
value: surface ?? around,
|
|
25
|
-
children: /* @__PURE__ */ jsx(TooltipProvider, { children: surface ? /* @__PURE__ */ jsx("div", {
|
|
26
|
-
"data-slot": "siyahi-provider",
|
|
27
|
-
"data-surface": surface,
|
|
28
|
-
className: "contents",
|
|
29
|
-
children
|
|
30
|
-
}) : children })
|
|
31
|
-
})
|
|
24
|
+
children: /* @__PURE__ */ jsx(TooltipProvider, { children })
|
|
32
25
|
});
|
|
33
26
|
}
|
|
34
27
|
function useLocale() {
|
|
35
28
|
return use(LocaleContext);
|
|
36
29
|
}
|
|
37
|
-
function useSurface() {
|
|
38
|
-
return use(SurfaceContext);
|
|
39
|
-
}
|
|
40
30
|
//#endregion
|
|
41
|
-
export { SiyahiProvider, useLocale
|
|
31
|
+
export { SiyahiProvider, useLocale };
|