@siyahi/ui 0.1.9-next.22 → 0.1.9-next.24
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 +3 -2
- package/agents/examples/accordion.tsx +7 -7
- package/agents/examples/alert.tsx +16 -15
- package/agents/examples/badge.tsx +20 -12
- package/agents/examples/bar-list-labels.tsx +6 -6
- package/agents/examples/bar-list-sides.tsx +8 -8
- package/agents/examples/bar-list.tsx +8 -8
- package/agents/examples/breadcrumb.tsx +3 -3
- package/agents/examples/callout.tsx +15 -15
- package/agents/examples/card.tsx +3 -3
- package/agents/examples/change-bar.tsx +21 -21
- package/agents/examples/chart-area.tsx +11 -11
- package/agents/examples/chart-bar-flows.tsx +1 -1
- package/agents/examples/chart-bar-hourly.tsx +1 -1
- package/agents/examples/chart-bar-losses.tsx +3 -3
- package/agents/examples/chart-bar-teams.tsx +72 -0
- package/agents/examples/chart-bar-years.tsx +5 -5
- package/agents/examples/chart-bar.tsx +10 -10
- package/agents/examples/chart-category-ticks.tsx +6 -6
- package/agents/examples/chart-line.tsx +17 -17
- package/agents/examples/collapsible.tsx +4 -2
- package/agents/examples/command.tsx +6 -6
- package/agents/examples/context-menu.tsx +2 -2
- package/agents/examples/data-bar.tsx +32 -45
- package/agents/examples/data-table-compact.tsx +31 -30
- package/agents/examples/data-table-filters.tsx +20 -20
- package/agents/examples/data-table.tsx +31 -30
- package/agents/examples/delta.tsx +11 -6
- package/agents/examples/dialog.tsx +3 -3
- package/agents/examples/distribution-bar-tug.tsx +15 -15
- package/agents/examples/dropdown-menu.tsx +2 -2
- package/agents/examples/heatmap-calendar.tsx +6 -6
- package/agents/examples/heatmap-status.tsx +1 -1
- package/agents/examples/heatmap-weekday.tsx +7 -7
- package/agents/examples/input-states.tsx +9 -9
- package/agents/examples/input.tsx +3 -3
- package/agents/examples/local-time.tsx +1 -1
- package/agents/examples/metric-strip.tsx +8 -8
- package/agents/examples/page-hero.tsx +2 -2
- package/agents/examples/popover.tsx +3 -3
- package/agents/examples/price-chart.tsx +3 -3
- package/agents/examples/progress-tone.tsx +10 -9
- package/agents/examples/progress.tsx +1 -1
- package/agents/examples/range-position-table.tsx +31 -31
- package/agents/examples/range-position.tsx +18 -18
- package/agents/examples/section-cards-select.tsx +11 -10
- package/agents/examples/section-cards-trend.tsx +4 -4
- package/agents/examples/section-cards.tsx +13 -13
- package/agents/examples/select.tsx +9 -9
- package/agents/examples/separator.tsx +3 -3
- package/agents/examples/sheet.tsx +1 -1
- package/agents/examples/slider.tsx +1 -1
- package/agents/examples/surfaces.tsx +16 -18
- package/agents/examples/tabs.tsx +7 -7
- package/agents/examples/target-rows.tsx +25 -23
- package/agents/examples/tooltip.tsx +2 -2
- package/agents/examples/treemap.tsx +27 -24
- package/agents/manifest.json +15 -15
- package/dist/components/registry/charts/bar-chart-card.d.ts +1 -1
- package/dist/components/registry/charts/line-chart-card.d.ts +1 -1
- package/dist/components/registry/charts/line-chart-card.js +1 -1
- package/dist/components/siyahi/callout.d.ts +5 -12
- package/dist/components/siyahi/callout.js +5 -11
- package/dist/components/siyahi/delta.js +2 -2
- package/dist/components/siyahi/status-alert.d.ts +15 -0
- package/dist/components/siyahi/status-alert.js +29 -0
- package/dist/components/siyahi/status-badge.d.ts +15 -0
- package/dist/components/siyahi/status-badge.js +24 -0
- package/dist/components/siyahi/tone-progress.d.ts +1 -1
- package/dist/components/siyahi/tone-progress.js +1 -1
- package/dist/components/siyahi/treemap.d.ts +4 -4
- package/dist/components/siyahi/treemap.js +2 -2
- package/dist/index.d.ts +5 -4
- package/dist/index.js +3 -2
- package/dist/lib/chart-frame.js +1 -1
- package/dist/lib/chart-series.d.ts +1 -1
- package/dist/lib/tone.d.ts +36 -0
- package/dist/lib/tone.js +35 -0
- package/package.json +1 -1
- package/styles/siyahi.css +7 -5
- package/agents/examples/chart-bar-sectors.tsx +0 -72
- package/dist/components/siyahi/warning-alert.d.ts +0 -10
- package/dist/components/siyahi/warning-alert.js +0 -20
|
@@ -13,11 +13,11 @@ import {
|
|
|
13
13
|
export default function DialogExample() {
|
|
14
14
|
return (
|
|
15
15
|
<Dialog>
|
|
16
|
-
<DialogTrigger render={<Button variant="outline" className="w-fit" />}>Show
|
|
16
|
+
<DialogTrigger render={<Button variant="outline" className="w-fit" />}>Show parcels</DialogTrigger>
|
|
17
17
|
<DialogContent>
|
|
18
18
|
<DialogHeader>
|
|
19
|
-
<DialogTitle>
|
|
20
|
-
<DialogDescription>Each
|
|
19
|
+
<DialogTitle>Parcels for this order</DialogTitle>
|
|
20
|
+
<DialogDescription>Each parcel this order was split into, earliest first.</DialogDescription>
|
|
21
21
|
</DialogHeader>
|
|
22
22
|
<DialogFooter>
|
|
23
23
|
<DialogClose render={<Button variant="outline" />}>Close</DialogClose>
|
|
@@ -11,17 +11,17 @@ import {
|
|
|
11
11
|
type DistributionSegment,
|
|
12
12
|
} from "@siyahi/ui";
|
|
13
13
|
|
|
14
|
-
// Each
|
|
15
|
-
const
|
|
16
|
-
{ name: "
|
|
17
|
-
{ name: "
|
|
18
|
-
{ name: "
|
|
19
|
-
{ name: "
|
|
20
|
-
{ name: "
|
|
21
|
-
{ name: "
|
|
14
|
+
// Each finished marketing campaign's net return, ₹: sales it brought in less what it cost; made-up figures.
|
|
15
|
+
const campaigns = [
|
|
16
|
+
{ name: "Festive sale", value: 61000 },
|
|
17
|
+
{ name: "Referrals", value: 38000 },
|
|
18
|
+
{ name: "Email win-back", value: 17000 },
|
|
19
|
+
{ name: "Billboards", value: -26000 },
|
|
20
|
+
{ name: "Podcast ads", value: -14000 },
|
|
21
|
+
{ name: "Trade fair", value: -6000 },
|
|
22
22
|
];
|
|
23
|
-
const won =
|
|
24
|
-
const lost =
|
|
23
|
+
const won = campaigns.filter((c) => c.value > 0).reduce((sum, c) => sum + c.value, 0);
|
|
24
|
+
const lost = campaigns.filter((c) => c.value < 0).reduce((sum, c) => sum + c.value, 0);
|
|
25
25
|
// One scale both ways, so whichever side reaches farther is the net.
|
|
26
26
|
const reach = Math.max(won, -lost);
|
|
27
27
|
|
|
@@ -31,7 +31,7 @@ export default function DistributionBarTugExample() {
|
|
|
31
31
|
<Card>
|
|
32
32
|
<CardHeader>
|
|
33
33
|
<CardTitle>The tug-of-war</CardTitle>
|
|
34
|
-
<CardDescription>Each
|
|
34
|
+
<CardDescription>Each finished campaign, losses left of break-even and gains right</CardDescription>
|
|
35
35
|
</CardHeader>
|
|
36
36
|
<CardContent>
|
|
37
37
|
<div className="flex flex-col gap-2">
|
|
@@ -42,7 +42,7 @@ export default function DistributionBarTugExample() {
|
|
|
42
42
|
markers={[{ at: 0 }]}
|
|
43
43
|
highlighted={focus?.name ?? null}
|
|
44
44
|
onHover={setFocus}
|
|
45
|
-
segments={
|
|
45
|
+
segments={campaigns.map(({ name, value }) => ({
|
|
46
46
|
name,
|
|
47
47
|
value,
|
|
48
48
|
color: value > 0 ? "var(--positive)" : "var(--negative)",
|
|
@@ -50,11 +50,11 @@ export default function DistributionBarTugExample() {
|
|
|
50
50
|
/>
|
|
51
51
|
<div className="grid grid-cols-3 text-xs text-muted-foreground tabular-nums">
|
|
52
52
|
<span>
|
|
53
|
-
|
|
53
|
+
lost <Delta value={lost} format="money" />
|
|
54
54
|
</span>
|
|
55
55
|
<span className="text-center">break-even</span>
|
|
56
56
|
<span className="text-right">
|
|
57
|
-
|
|
57
|
+
earned <Delta value={won} format="money" />
|
|
58
58
|
</span>
|
|
59
59
|
</div>
|
|
60
60
|
</div>
|
|
@@ -66,7 +66,7 @@ export default function DistributionBarTugExample() {
|
|
|
66
66
|
<Delta value={focus.value} format="money" />
|
|
67
67
|
</p>
|
|
68
68
|
) : (
|
|
69
|
-
<p className="text-muted-foreground">Hover a band to see its
|
|
69
|
+
<p className="text-muted-foreground">Hover a band to see its campaign.</p>
|
|
70
70
|
)}
|
|
71
71
|
</CardFooter>
|
|
72
72
|
</Card>
|
|
@@ -19,8 +19,8 @@ export default function DropdownMenuExample() {
|
|
|
19
19
|
</DropdownMenuTrigger>
|
|
20
20
|
<DropdownMenuContent>
|
|
21
21
|
<DropdownMenuGroup>
|
|
22
|
-
<DropdownMenuLabel>
|
|
23
|
-
<DropdownMenuItem>View
|
|
22
|
+
<DropdownMenuLabel>Order</DropdownMenuLabel>
|
|
23
|
+
<DropdownMenuItem>View parcels</DropdownMenuItem>
|
|
24
24
|
<DropdownMenuItem>Export CSV</DropdownMenuItem>
|
|
25
25
|
</DropdownMenuGroup>
|
|
26
26
|
<DropdownMenuSeparator />
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
CardTitle,
|
|
14
14
|
} from "@siyahi/ui";
|
|
15
15
|
|
|
16
|
-
// A year of
|
|
16
|
+
// A year of working days with a count of production deploys on each.
|
|
17
17
|
const data = Array.from({ length: 365 }, (_, i) => {
|
|
18
18
|
const day = new Date(Date.UTC(2025, 9, 20 + i));
|
|
19
19
|
const weekday = day.getUTCDay();
|
|
@@ -29,11 +29,11 @@ export default function HeatmapCalendarExample() {
|
|
|
29
29
|
return (
|
|
30
30
|
<Card>
|
|
31
31
|
<CardHeader>
|
|
32
|
-
<CardTitle>
|
|
32
|
+
<CardTitle>Deploys per day</CardTitle>
|
|
33
33
|
<CardDescription>The last 12 months; counts use a single-hue fade of --chart-1</CardDescription>
|
|
34
34
|
</CardHeader>
|
|
35
35
|
<CardContent>
|
|
36
|
-
<CalendarHeatmap data={data} labels={{ heatmapLabel: "
|
|
36
|
+
<CalendarHeatmap data={data} labels={{ heatmapLabel: "Deploys per day over the last 12 months" }}>
|
|
37
37
|
<CalendarHeatmapBody>
|
|
38
38
|
{({ activity, dayIndex, weekIndex }) => (
|
|
39
39
|
<CalendarHeatmapBlock
|
|
@@ -49,10 +49,10 @@ export default function HeatmapCalendarExample() {
|
|
|
49
49
|
<div className="flex w-full flex-wrap items-center justify-between gap-x-6 gap-y-2">
|
|
50
50
|
<p aria-live="polite" className="text-sm">
|
|
51
51
|
{picked
|
|
52
|
-
? `${picked.date}: ${count(picked.value)}
|
|
53
|
-
: "Select a day for its
|
|
52
|
+
? `${picked.date}: ${count(picked.value)} deploys`
|
|
53
|
+
: "Select a day for its deploy count. Use arrow keys to move between days."}
|
|
54
54
|
</p>
|
|
55
|
-
<CalendarHeatmapLegend labels={{ less: "0
|
|
55
|
+
<CalendarHeatmapLegend labels={{ less: "0 deploys", more: `${count(busiest)} deploys` }} />
|
|
56
56
|
</div>
|
|
57
57
|
</CalendarHeatmapFooter>
|
|
58
58
|
</CalendarHeatmap>
|
|
@@ -26,7 +26,7 @@ export default function HeatmapStatusExample() {
|
|
|
26
26
|
return (
|
|
27
27
|
<Card>
|
|
28
28
|
<CardHeader>
|
|
29
|
-
<CardTitle>
|
|
29
|
+
<CardTitle>Checkout API</CardTitle>
|
|
30
30
|
<CardDescription>Daily health: healthy, degraded or critical</CardDescription>
|
|
31
31
|
</CardHeader>
|
|
32
32
|
<CardContent>
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
WeekdayHeatmapLegend,
|
|
13
13
|
} from "@siyahi/ui";
|
|
14
14
|
|
|
15
|
-
//
|
|
15
|
+
// Support tickets opened by weekday and office hour; the overnight queue lands at 9.
|
|
16
16
|
const data = [1, 2, 3, 4, 5].flatMap((weekday) =>
|
|
17
17
|
[9, 10, 11, 12, 13, 14, 15].map((hour) => ({
|
|
18
18
|
weekday,
|
|
@@ -33,8 +33,8 @@ export default function HeatmapWeekdayExample() {
|
|
|
33
33
|
return (
|
|
34
34
|
<Card>
|
|
35
35
|
<CardHeader>
|
|
36
|
-
<CardTitle>When
|
|
37
|
-
<CardDescription>Weekday by hour in India Standard Time,
|
|
36
|
+
<CardTitle>When support tickets arrive</CardTitle>
|
|
37
|
+
<CardDescription>Weekday by hour in India Standard Time, office hours only</CardDescription>
|
|
38
38
|
</CardHeader>
|
|
39
39
|
{/* Seven hours by five days is a small grid: capped, it keeps square cells, and the legend and the answer
|
|
40
40
|
sit beside it instead of a wide empty card. */}
|
|
@@ -53,15 +53,15 @@ export default function HeatmapWeekdayExample() {
|
|
|
53
53
|
<div className="flex flex-col items-start gap-3 text-sm">
|
|
54
54
|
<WeekdayHeatmapLegend
|
|
55
55
|
className="ml-0"
|
|
56
|
-
labels={{ less: "0
|
|
56
|
+
labels={{ less: "0 tickets", more: `${count(busiest.value)} tickets an hour` }}
|
|
57
57
|
/>
|
|
58
58
|
<p>
|
|
59
|
-
Busiest: {DAYS[busiest.weekday]} at {hourLabel(busiest.hour)}, {count(busiest.value)}
|
|
59
|
+
Busiest: {DAYS[busiest.weekday]} at {hourLabel(busiest.hour)}, {count(busiest.value)} tickets
|
|
60
60
|
</p>
|
|
61
61
|
<p aria-live="polite" className="text-muted-foreground">
|
|
62
62
|
{picked
|
|
63
|
-
? `${DAYS[picked.weekday]}, ${hourLabel(picked.hour)} IST: ${count(picked.value)}
|
|
64
|
-
: "Select a cell for its
|
|
63
|
+
? `${DAYS[picked.weekday]}, ${hourLabel(picked.hour)} IST: ${count(picked.value)} tickets`
|
|
64
|
+
: "Select a cell for its ticket count. Use arrow keys to move between cells."}
|
|
65
65
|
</p>
|
|
66
66
|
</div>
|
|
67
67
|
</div>
|
|
@@ -10,23 +10,23 @@ export default function InputStatesExample() {
|
|
|
10
10
|
</label>
|
|
11
11
|
<Input id="budget" inputMode="numeric" defaultValue="25,000" aria-describedby="budget-hint" />
|
|
12
12
|
<p id="budget-hint" className="text-sm text-muted-foreground">
|
|
13
|
-
In rupees, before
|
|
13
|
+
In rupees, before tax
|
|
14
14
|
</p>
|
|
15
15
|
</div>
|
|
16
16
|
<div className="grid gap-1.5">
|
|
17
|
-
<label htmlFor="
|
|
18
|
-
|
|
17
|
+
<label htmlFor="pin" className="text-sm font-medium">
|
|
18
|
+
PIN code
|
|
19
19
|
</label>
|
|
20
|
-
<Input id="
|
|
21
|
-
<p id="
|
|
22
|
-
A
|
|
20
|
+
<Input id="pin" defaultValue="56/001" aria-invalid aria-describedby="pin-error" />
|
|
21
|
+
<p id="pin-error" className="text-sm text-destructive">
|
|
22
|
+
A PIN code is six digits, such as 560001
|
|
23
23
|
</p>
|
|
24
24
|
</div>
|
|
25
25
|
<div className="grid gap-1.5">
|
|
26
|
-
<label htmlFor="
|
|
27
|
-
|
|
26
|
+
<label htmlFor="team" className="text-sm font-medium text-muted-foreground">
|
|
27
|
+
Team
|
|
28
28
|
</label>
|
|
29
|
-
<Input id="
|
|
29
|
+
<Input id="team" defaultValue="Finance" disabled />
|
|
30
30
|
</div>
|
|
31
31
|
</div>
|
|
32
32
|
);
|
|
@@ -4,14 +4,14 @@ import { SearchIcon } from "lucide-react";
|
|
|
4
4
|
export default function InputExample() {
|
|
5
5
|
return (
|
|
6
6
|
<div className="flex max-w-sm flex-col gap-3">
|
|
7
|
-
<Input placeholder="
|
|
7
|
+
<Input placeholder="Order number" aria-label="Order number" />
|
|
8
8
|
<InputGroup>
|
|
9
9
|
<InputGroupAddon>
|
|
10
10
|
<SearchIcon />
|
|
11
11
|
</InputGroupAddon>
|
|
12
|
-
<InputGroupInput placeholder="Search
|
|
12
|
+
<InputGroupInput placeholder="Search customers" aria-label="Search customers" />
|
|
13
13
|
</InputGroup>
|
|
14
|
-
<Textarea placeholder="Note for this
|
|
14
|
+
<Textarea placeholder="Note for this order" aria-label="Note" />
|
|
15
15
|
</div>
|
|
16
16
|
);
|
|
17
17
|
}
|
|
@@ -4,7 +4,7 @@ export default function LocalTimeExample() {
|
|
|
4
4
|
return (
|
|
5
5
|
<>
|
|
6
6
|
<p>
|
|
7
|
-
|
|
7
|
+
Figures as of <LocalTime value="2026-10-20T10:00:00Z" />. Hover the time to see it on your own clock.
|
|
8
8
|
</p>
|
|
9
9
|
<p>
|
|
10
10
|
Daily snapshot of <LocalTime value="2026-06-26T04:11:00Z" withDate />.
|
|
@@ -5,33 +5,33 @@ export default function MetricStripExample() {
|
|
|
5
5
|
// trend is each figure's month-end run, oldest first.
|
|
6
6
|
const items: MetricStripItem[] = [
|
|
7
7
|
{
|
|
8
|
-
label: "
|
|
8
|
+
label: "Revenue",
|
|
9
9
|
value: money(4512300),
|
|
10
10
|
change: 0.031,
|
|
11
11
|
note: "vs Sep",
|
|
12
12
|
trend: [3820000, 3950000, 4110000, 4020000, 4380000, 4512300],
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
label: "
|
|
15
|
+
label: "Target",
|
|
16
16
|
value: moneyCompact(4025000),
|
|
17
17
|
change: 85000,
|
|
18
18
|
changeFormat: "money",
|
|
19
19
|
trend: [3600000, 3685000, 3770000, 3855000, 3940000, 4025000],
|
|
20
20
|
},
|
|
21
|
-
{ label: "
|
|
21
|
+
{ label: "Gross margin", value: pct(0.142), change: -0.004, trend: [0.151, 0.149, 0.152, 0.144, 0.146, 0.142] },
|
|
22
22
|
{
|
|
23
|
-
label: "
|
|
23
|
+
label: "Cash flow",
|
|
24
24
|
value: moneyCompact(-61200),
|
|
25
25
|
change: -61200,
|
|
26
26
|
changeFormat: "money",
|
|
27
27
|
trend: [14200, -3800, 9100, 2600, -18400, -61200],
|
|
28
28
|
},
|
|
29
|
-
{ label: "
|
|
30
|
-
{ label: "
|
|
29
|
+
{ label: "Gift cards", value: moneyCompact(38400), change: 0.18, trend: [4100, 0, 12800, 3300, 9900, 8300] },
|
|
30
|
+
{ label: "Products", value: count(42), note: "3 added in Oct", trend: [38, 39, 39, 40, 39, 42] },
|
|
31
31
|
];
|
|
32
32
|
return (
|
|
33
33
|
<MetricStrip
|
|
34
|
-
title="
|
|
34
|
+
title="Revenue up 3.1% in October"
|
|
35
35
|
description="Month-end figures with the six-month run behind each"
|
|
36
36
|
action={
|
|
37
37
|
<ToggleGroup defaultValue={["1M"]} variant="outline" size="sm" aria-label="Period">
|
|
@@ -40,7 +40,7 @@ export default function MetricStripExample() {
|
|
|
40
40
|
</ToggleGroup>
|
|
41
41
|
}
|
|
42
42
|
items={items}
|
|
43
|
-
footer={<p className="text-muted-foreground">
|
|
43
|
+
footer={<p className="text-muted-foreground">Booked up to 31 Oct 2026</p>}
|
|
44
44
|
/>
|
|
45
45
|
);
|
|
46
46
|
}
|
|
@@ -19,8 +19,8 @@ export default function PageHeroExample() {
|
|
|
19
19
|
<PageHero
|
|
20
20
|
eyebrow="@siyahi/ui"
|
|
21
21
|
title="Siyahi"
|
|
22
|
-
lead="Ink for numbers. A design system for pages people read figures from:
|
|
23
|
-
detail="Stock shadcn/ui on Base UI and Tailwind v4, with a
|
|
22
|
+
lead="Ink for numbers. A design system for pages people read figures from: dashboards, ledgers, reports."
|
|
23
|
+
detail="Stock shadcn/ui on Base UI and Tailwind v4, with a theme for figures, charts and tables that fit a phone, Indian-aware formatters and a lint. Siyahi is Hindi for ink."
|
|
24
24
|
actions={
|
|
25
25
|
<>
|
|
26
26
|
<Button nativeButton={false} render={<a href="#/data" />}>
|
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
export default function PopoverExample() {
|
|
12
12
|
return (
|
|
13
13
|
<Popover>
|
|
14
|
-
<PopoverTrigger render={<Button variant="outline" className="w-fit" />}>How is this
|
|
14
|
+
<PopoverTrigger render={<Button variant="outline" className="w-fit" />}>How is this counted?</PopoverTrigger>
|
|
15
15
|
<PopoverContent align="start">
|
|
16
16
|
<PopoverHeader>
|
|
17
|
-
<PopoverTitle>
|
|
18
|
-
<PopoverDescription>
|
|
17
|
+
<PopoverTitle>Paid orders</PopoverTitle>
|
|
18
|
+
<PopoverDescription>Revenue counts paid orders, less refunds, on the day each was placed.</PopoverDescription>
|
|
19
19
|
</PopoverHeader>
|
|
20
20
|
</PopoverContent>
|
|
21
21
|
</Popover>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, PriceChart } from "@siyahi/ui";
|
|
2
2
|
|
|
3
|
-
// A made-up daily
|
|
3
|
+
// A made-up daily series for one year: the average order value, in rupees.
|
|
4
4
|
const data = Array.from({ length: 250 }, (_, i) => {
|
|
5
5
|
const day = new Date(Date.UTC(2025, 9, 20 + Math.floor((i * 7) / 5)));
|
|
6
6
|
return { time: day.toISOString().slice(0, 10), value: 1500 + i * 1.2 + Math.sin(i / 9) * 60 + Math.sin(i / 3) * 18 };
|
|
@@ -10,8 +10,8 @@ export default function PriceChartExample() {
|
|
|
10
10
|
return (
|
|
11
11
|
<Card>
|
|
12
12
|
<CardHeader>
|
|
13
|
-
<CardTitle>
|
|
14
|
-
<CardDescription>Daily
|
|
13
|
+
<CardTitle>Average order value</CardTitle>
|
|
14
|
+
<CardDescription>Daily, one year, ₹</CardDescription>
|
|
15
15
|
</CardHeader>
|
|
16
16
|
<CardContent>
|
|
17
17
|
<PriceChart data={data} height={256} />
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { ToneProgress, useFormat } from "@siyahi/ui";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
{
|
|
6
|
-
{
|
|
3
|
+
// Each sales channel's profit or loss this quarter, and its share of all the profit and loss booked; made-up figures.
|
|
4
|
+
const channels = [
|
|
5
|
+
{ channel: "Online", profit: 84200, share: 0.41 },
|
|
6
|
+
{ channel: "Retail", profit: -61200, share: 0.3 },
|
|
7
|
+
{ channel: "Export", profit: 21000, share: 0.1 },
|
|
7
8
|
];
|
|
8
9
|
|
|
9
10
|
export default function ProgressToneExample() {
|
|
10
11
|
const { pct } = useFormat();
|
|
11
12
|
return (
|
|
12
13
|
<div className="flex max-w-sm flex-col gap-3 text-sm">
|
|
13
|
-
{
|
|
14
|
-
<div key={p.
|
|
15
|
-
<span className="w-16 font-medium">{p.
|
|
14
|
+
{channels.map((p) => (
|
|
15
|
+
<div key={p.channel} className="flex items-center gap-3">
|
|
16
|
+
<span className="w-16 font-medium">{p.channel}</span>
|
|
16
17
|
<ToneProgress
|
|
17
|
-
tone={p.
|
|
18
|
+
tone={p.profit >= 0 ? "positive" : "negative"}
|
|
18
19
|
value={p.share * 100}
|
|
19
|
-
aria-label={`${p.
|
|
20
|
+
aria-label={`${p.channel}'s share of the quarter's profit and loss`}
|
|
20
21
|
getAriaValueText={() => pct(p.share)}
|
|
21
22
|
className="w-24"
|
|
22
23
|
/>
|
|
@@ -3,7 +3,7 @@ import { Progress, ProgressLabel, ProgressValue } from "@siyahi/ui";
|
|
|
3
3
|
export default function ProgressExample() {
|
|
4
4
|
return (
|
|
5
5
|
<Progress value={64} className="max-w-sm">
|
|
6
|
-
<ProgressLabel>
|
|
6
|
+
<ProgressLabel>Orders imported</ProgressLabel>
|
|
7
7
|
<ProgressValue />
|
|
8
8
|
</Progress>
|
|
9
9
|
);
|
|
@@ -16,61 +16,61 @@ import {
|
|
|
16
16
|
type DataTableColumnDef,
|
|
17
17
|
} from "@siyahi/ui";
|
|
18
18
|
|
|
19
|
-
interface
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
|
|
19
|
+
interface Service {
|
|
20
|
+
service: string;
|
|
21
|
+
/** Today's 95th-percentile response time and the fastest and slowest day of the last 30, in ms; made-up figures. */
|
|
22
|
+
today: number;
|
|
23
23
|
low: number;
|
|
24
24
|
high: number;
|
|
25
|
-
/** How far up its range
|
|
25
|
+
/** How far up its range today sits, 0 at the fastest day and 1 at the slowest, so the column sorts. */
|
|
26
26
|
position: number;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
const service = (name: string, today: number, low: number, high: number): Service => ({
|
|
30
|
+
service: name,
|
|
31
|
+
today,
|
|
32
32
|
low,
|
|
33
33
|
high,
|
|
34
|
-
position: (
|
|
34
|
+
position: (today - low) / (high - low),
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
const services: Service[] = [
|
|
38
|
+
service("search", 284, 241, 292),
|
|
39
|
+
service("catalogue", 187, 131, 201),
|
|
40
|
+
service("checkout", 329, 265, 342),
|
|
41
|
+
service("images", 415, 359, 459),
|
|
42
|
+
service("payments", 460, 399, 529),
|
|
43
|
+
service("login", 175, 161, 203),
|
|
44
44
|
];
|
|
45
45
|
|
|
46
|
-
function
|
|
47
|
-
return useFormat().
|
|
46
|
+
function Milliseconds({ value }: { value: number }) {
|
|
47
|
+
return `${useFormat().count(value)} ms`;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
const header = () => <DataTableSortHeader />;
|
|
51
51
|
|
|
52
|
-
const columns: DataTableColumnDef<
|
|
53
|
-
{ accessorKey: "
|
|
52
|
+
const columns: DataTableColumnDef<Service>[] = [
|
|
53
|
+
{ accessorKey: "service", header, size: 130, meta: { label: "Service", compact: true } },
|
|
54
54
|
{
|
|
55
|
-
accessorKey: "
|
|
55
|
+
accessorKey: "today",
|
|
56
56
|
header,
|
|
57
57
|
size: 120,
|
|
58
|
-
meta: { label: "
|
|
59
|
-
cell: ({ row }) => <
|
|
58
|
+
meta: { label: "p95 today", variant: "number" },
|
|
59
|
+
cell: ({ row }) => <Milliseconds value={row.original.today} />,
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
accessorKey: "position",
|
|
63
63
|
header,
|
|
64
64
|
size: 200,
|
|
65
|
-
meta: { label: "
|
|
65
|
+
meta: { label: "30-day range", compact: true },
|
|
66
66
|
cell: ({ row }) => (
|
|
67
67
|
<RangePosition
|
|
68
68
|
variant="compact"
|
|
69
69
|
low={row.original.low}
|
|
70
70
|
high={row.original.high}
|
|
71
|
-
value={row.original.
|
|
72
|
-
lowLabel="
|
|
73
|
-
highLabel="
|
|
71
|
+
value={row.original.today}
|
|
72
|
+
lowLabel="30-day fastest"
|
|
73
|
+
highLabel="30-day slowest"
|
|
74
74
|
/>
|
|
75
75
|
),
|
|
76
76
|
},
|
|
@@ -80,17 +80,17 @@ export default function RangePositionTableExample() {
|
|
|
80
80
|
return (
|
|
81
81
|
<Card>
|
|
82
82
|
<CardHeader>
|
|
83
|
-
<CardTitle>
|
|
83
|
+
<CardTitle>Search is near its slowest of the month, login near its fastest</CardTitle>
|
|
84
84
|
<CardDescription>
|
|
85
|
-
Each
|
|
85
|
+
Each service's response time today on a track from its fastest day to its slowest; sort to rank them
|
|
86
86
|
</CardDescription>
|
|
87
87
|
</CardHeader>
|
|
88
88
|
<CardContent>
|
|
89
|
-
<DataTableRoot data={
|
|
89
|
+
<DataTableRoot data={services} columns={columns}>
|
|
90
90
|
<DataTableToolbarSection>
|
|
91
91
|
<DataTableCompactColumnsToggle />
|
|
92
92
|
</DataTableToolbarSection>
|
|
93
|
-
<DataTable aria-label="
|
|
93
|
+
<DataTable aria-label="Services in their 30-day range">
|
|
94
94
|
<DataTableHeader />
|
|
95
95
|
<DataTableBody />
|
|
96
96
|
</DataTable>
|
|
@@ -10,42 +10,42 @@ import {
|
|
|
10
10
|
useFormat,
|
|
11
11
|
} from "@siyahi/ui";
|
|
12
12
|
|
|
13
|
-
//
|
|
14
|
-
const low =
|
|
15
|
-
const high =
|
|
16
|
-
const
|
|
13
|
+
// Checkout's daily 95th-percentile response time over the last 30 days, in ms; made-up figures.
|
|
14
|
+
const low = 161;
|
|
15
|
+
const high = 203;
|
|
16
|
+
const today = 175;
|
|
17
17
|
|
|
18
18
|
export default function RangePositionExample() {
|
|
19
19
|
const f = useFormat();
|
|
20
|
-
const
|
|
20
|
+
const ms = (value: number) => `${f.count(value)} ms`;
|
|
21
21
|
return (
|
|
22
22
|
// Side by side once the card, not the screen, has room: in a narrow panel on a wide screen they stack.
|
|
23
23
|
<Card className="@container/range">
|
|
24
24
|
<CardHeader>
|
|
25
|
-
<CardTitle>
|
|
26
|
-
<CardDescription>
|
|
25
|
+
<CardTitle>Checkout sits {f.pct((today - low) / (high - low), 0)} of the way up its 30-day range</CardTitle>
|
|
26
|
+
<CardDescription>Today's response time against the month's fastest and slowest day</CardDescription>
|
|
27
27
|
</CardHeader>
|
|
28
28
|
<CardContent>
|
|
29
29
|
<div className="flex flex-col gap-8 @xl/range:flex-row @xl/range:items-end">
|
|
30
30
|
<DataList className="@xl/range:w-56 @xl/range:shrink-0">
|
|
31
|
-
<DataListItem label="
|
|
32
|
-
<span className="tabular-nums">{
|
|
31
|
+
<DataListItem label="Fastest day, 3 weeks ago">
|
|
32
|
+
<span className="tabular-nums">{ms(low)}</span>
|
|
33
33
|
</DataListItem>
|
|
34
|
-
<DataListItem label="
|
|
35
|
-
<span className="tabular-nums">{
|
|
34
|
+
<DataListItem label="Slowest day, 9 days ago">
|
|
35
|
+
<span className="tabular-nums">{ms(high)}</span>
|
|
36
36
|
</DataListItem>
|
|
37
|
-
<DataListItem label="
|
|
38
|
-
<span className="tabular-nums">{
|
|
37
|
+
<DataListItem label="Today, 95th percentile">
|
|
38
|
+
<span className="tabular-nums">{ms(today)}</span>
|
|
39
39
|
</DataListItem>
|
|
40
40
|
</DataList>
|
|
41
41
|
<RangePosition
|
|
42
42
|
low={low}
|
|
43
43
|
high={high}
|
|
44
|
-
value={
|
|
45
|
-
lowLabel="
|
|
46
|
-
highLabel="
|
|
47
|
-
caption="of the way up the
|
|
48
|
-
valueFormatter={
|
|
44
|
+
value={today}
|
|
45
|
+
lowLabel="30-day fastest"
|
|
46
|
+
highLabel="30-day slowest"
|
|
47
|
+
caption="of the way up the 30-day range"
|
|
48
|
+
valueFormatter={ms}
|
|
49
49
|
className="@xl/range:flex-1"
|
|
50
50
|
/>
|
|
51
51
|
</div>
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
import { Delta, SectionCards, SiyahiProvider, useFormat, type SectionCard } from "@siyahi/ui";
|
|
2
2
|
import { useState } from "react";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
{ label: "
|
|
7
|
-
{ label: "
|
|
8
|
-
{ label: "
|
|
4
|
+
// Each sales channel's profit this quarter and its orders; made-up figures.
|
|
5
|
+
const channels = [
|
|
6
|
+
{ label: "All", net: 110200, orders: 181 },
|
|
7
|
+
{ label: "Online", net: 171400, orders: 164 },
|
|
8
|
+
{ label: "Wholesale", net: 0, orders: 0 },
|
|
9
|
+
{ label: "Marketplace", net: -61200, orders: 17 },
|
|
9
10
|
];
|
|
10
11
|
|
|
11
12
|
export default function SectionCardsSelectExample() {
|
|
12
13
|
const [scope, setScope] = useState("All");
|
|
13
14
|
const { count } = useFormat();
|
|
14
|
-
const items: SectionCard[] =
|
|
15
|
+
const items: SectionCard[] = channels.map((c) => ({
|
|
15
16
|
label: c.label,
|
|
16
17
|
value: <Delta value={c.net} format="money" />,
|
|
17
|
-
detail: `${count(c.
|
|
18
|
-
// Nothing to show for a
|
|
19
|
-
disabled: c.
|
|
18
|
+
detail: `${count(c.orders)} orders`,
|
|
19
|
+
// Nothing to show for a channel with no orders, so it cannot be picked.
|
|
20
|
+
disabled: c.orders === 0,
|
|
20
21
|
}));
|
|
21
22
|
return (
|
|
22
|
-
// On a ruled surface the tiles part with hairlines, as on a
|
|
23
|
+
// On a ruled surface the tiles part with hairlines, as on a dense operations screen, instead of sitting as cards.
|
|
23
24
|
<SiyahiProvider surface="ruled">
|
|
24
25
|
<div className="flex flex-col gap-3">
|
|
25
26
|
<SectionCards items={items} selected={scope} onSelect={setScope} />
|