@siyahi/ui 0.1.9-next.3 → 0.1.9-next.31
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 +251 -0
- package/README.md +94 -177
- package/THIRD_PARTY_NOTICES.md +11 -11
- package/agents/examples/accordion.tsx +39 -0
- package/agents/examples/alert.tsx +24 -0
- package/agents/examples/app-sidebar.tsx +40 -0
- package/agents/examples/avatar.tsx +24 -0
- package/agents/examples/badge.tsx +26 -0
- package/agents/examples/bar-list-labels.tsx +22 -0
- package/agents/examples/bar-list-sides.tsx +40 -0
- package/agents/examples/bar-list.tsx +24 -0
- package/agents/examples/breadcrumb.tsx +28 -0
- package/agents/examples/button-states.tsx +23 -0
- package/agents/examples/button.tsx +21 -0
- package/agents/examples/calendar.tsx +11 -0
- package/agents/examples/callout.tsx +33 -0
- package/agents/examples/card.tsx +36 -0
- package/agents/examples/change-bar.tsx +104 -0
- package/agents/examples/change-grid-money.tsx +36 -0
- package/agents/examples/change-grid.tsx +43 -0
- package/agents/examples/chart-area-log.tsx +45 -0
- package/agents/examples/chart-area.tsx +39 -0
- package/agents/examples/chart-bar-flows.tsx +32 -0
- package/agents/examples/chart-bar-hourly.tsx +28 -0
- package/agents/examples/chart-bar-losses.tsx +29 -0
- package/agents/examples/chart-bar-teams.tsx +72 -0
- package/agents/examples/chart-bar-years.tsx +42 -0
- package/agents/examples/chart-bar.tsx +56 -0
- package/agents/examples/chart-category-ticks.tsx +50 -0
- package/agents/examples/chart-line-events.tsx +47 -0
- package/agents/examples/chart-line-forecast.tsx +36 -0
- package/agents/examples/chart-line-log.tsx +39 -0
- package/agents/examples/chart-line-quiet.tsx +114 -0
- package/agents/examples/chart-line-timeline.tsx +41 -0
- package/agents/examples/chart-line.tsx +57 -0
- package/agents/examples/chart-panels.tsx +94 -0
- package/agents/examples/code-block.tsx +40 -0
- package/agents/examples/collapsible.tsx +18 -0
- package/agents/examples/command.tsx +29 -0
- package/agents/examples/context-menu.tsx +17 -0
- package/agents/examples/copy-button.tsx +8 -0
- package/agents/examples/data-bar.tsx +114 -0
- package/agents/examples/data-table-compact.tsx +93 -0
- package/agents/examples/data-table-filters.tsx +103 -0
- package/agents/examples/data-table.tsx +96 -0
- package/agents/examples/delta.tsx +18 -0
- package/agents/examples/dialog.tsx +28 -0
- package/agents/examples/distribution-bar-budget.tsx +30 -0
- package/agents/examples/distribution-bar-tug.tsx +74 -0
- package/agents/examples/drawdown-chart.tsx +35 -0
- package/agents/examples/dropdown-menu.tsx +31 -0
- package/agents/examples/field.tsx +108 -0
- package/agents/examples/formatters.tsx +42 -0
- package/agents/examples/heatmap-calendar-signed.tsx +67 -0
- package/agents/examples/heatmap-calendar.tsx +62 -0
- package/agents/examples/heatmap-status.tsx +61 -0
- package/agents/examples/heatmap-weekday.tsx +72 -0
- package/agents/examples/histogram-chart.tsx +28 -0
- package/agents/examples/input-states.tsx +23 -0
- package/agents/examples/input.tsx +17 -0
- package/agents/examples/local-time.tsx +14 -0
- package/agents/examples/metric-strip.tsx +46 -0
- package/agents/examples/overview-dashboard.tsx +180 -0
- package/agents/examples/page-hero.tsx +38 -0
- package/agents/examples/page-section.tsx +52 -0
- package/agents/examples/popover.tsx +23 -0
- package/agents/examples/price-chart.tsx +32 -0
- package/agents/examples/progress-tone.tsx +29 -0
- package/agents/examples/progress.tsx +10 -0
- package/agents/examples/range-position-table.tsx +113 -0
- package/agents/examples/range-position.tsx +55 -0
- package/agents/examples/scatter-chart-quadrants.tsx +63 -0
- package/agents/examples/scatter-chart-scales.tsx +46 -0
- package/agents/examples/scatter-chart.tsx +78 -0
- package/agents/examples/scroll-area.tsx +22 -0
- package/agents/examples/section-cards-select.tsx +28 -0
- package/agents/examples/section-cards-trend.tsx +32 -0
- package/agents/examples/section-cards.tsx +48 -0
- package/agents/examples/select.tsx +27 -0
- package/agents/examples/separator.tsx +13 -0
- package/agents/examples/sheet.tsx +15 -0
- package/agents/examples/skeleton.tsx +11 -0
- package/agents/examples/slider.tsx +5 -0
- package/agents/examples/slope-chart-market.tsx +33 -0
- package/agents/examples/slope-chart.tsx +26 -0
- package/agents/examples/stale-blocks.tsx +56 -0
- package/agents/examples/surfaces.tsx +116 -0
- package/agents/examples/table.tsx +60 -0
- package/agents/examples/tabs.tsx +16 -0
- package/agents/examples/target-rows.tsx +74 -0
- package/agents/examples/toggle-group.tsx +12 -0
- package/agents/examples/toggle.tsx +11 -0
- package/agents/examples/tooltip.tsx +13 -0
- package/agents/examples/treemap.tsx +93 -0
- package/agents/examples/waterfall-chart-stores.tsx +27 -0
- package/agents/examples/waterfall-chart.tsx +37 -0
- package/agents/manifest.json +1391 -0
- package/agents/report-rules.json +7 -0
- package/dist/components/registry/charts/area-chart-card.d.ts +7 -3
- package/dist/components/registry/charts/area-chart-card.js +56 -10
- package/dist/components/registry/charts/bar-chart-card.d.ts +1 -1
- package/dist/components/registry/charts/bar-chart-card.js +20 -22
- package/dist/components/registry/charts/line-chart-card.d.ts +3 -3
- package/dist/components/registry/charts/line-chart-card.js +44 -9
- package/dist/components/registry/dashboard-01/section-cards.d.ts +6 -0
- package/dist/components/registry/dashboard-01/section-cards.js +51 -35
- package/dist/components/registry/dashboardcn/bar-list.js +17 -10
- package/dist/components/registry/dashboardcn/distribution-bar.js +6 -4
- package/dist/components/registry/dashboardcn/kpi-row-card.d.ts +29 -0
- package/dist/components/registry/dashboardcn/kpi-row-card.js +81 -0
- package/dist/components/registry/dashboardcn/sparkline.d.ts +22 -0
- package/dist/components/registry/dashboardcn/sparkline.js +117 -0
- package/dist/components/registry/heatmap/calendar-heatmap.d.ts +11 -3
- package/dist/components/registry/heatmap/calendar-heatmap.js +164 -45
- package/dist/components/registry/heatmap/status-heatmap.d.ts +5 -3
- package/dist/components/registry/heatmap/status-heatmap.js +115 -54
- package/dist/components/registry/heatmap/weekday-heatmap.d.ts +9 -3
- package/dist/components/registry/heatmap/weekday-heatmap.js +83 -53
- package/dist/components/registry/niko-table/core/data-table-context.d.ts +18 -1
- package/dist/components/registry/niko-table/core/data-table-context.js +7 -1
- package/dist/components/registry/niko-table/core/data-table-grouped-row.js +3 -1
- package/dist/components/registry/niko-table/core/data-table-root.js +39 -4
- package/dist/components/registry/niko-table/core/data-table-structure.js +17 -12
- package/dist/components/registry/niko-table/core/data-table.d.ts +2 -2
- package/dist/components/registry/niko-table/core/data-table.js +5 -1
- package/dist/components/registry/niko-table/filters/table-faceted-filter.js +5 -5
- package/dist/components/registry/niko-table/filters/table-search-filter.js +1 -1
- package/dist/components/registry/niko-table/lib/flex-columns.d.ts +1 -1
- package/dist/components/registry/niko-table/lib/flex-columns.js +3 -3
- package/dist/components/registry/niko-table/lib/styles.d.ts +1 -1
- package/dist/components/registry/niko-table/lib/styles.js +3 -3
- package/dist/components/registry/niko-table/types/index.d.ts +9 -0
- package/dist/components/registry/niko-table/ui/table.js +2 -2
- package/dist/components/registry/sidebar-07/app-sidebar.d.ts +1 -1
- package/dist/components/registry/sidebar-07/app-sidebar.js +3 -1
- package/dist/components/registry/sidebar-07/nav-main.d.ts +2 -1
- package/dist/components/registry/sidebar-07/nav-main.js +16 -3
- package/dist/components/siyahi/callout.d.ts +17 -0
- package/dist/components/siyahi/callout.js +34 -0
- package/dist/components/siyahi/change-bar.d.ts +21 -0
- package/dist/components/siyahi/change-bar.js +35 -0
- package/dist/components/siyahi/change-grid.d.ts +31 -0
- package/dist/components/siyahi/change-grid.js +74 -0
- package/dist/components/siyahi/data-bar.d.ts +19 -0
- package/dist/components/siyahi/data-bar.js +29 -0
- package/dist/components/siyahi/data-table-compact-columns-toggle.d.ts +4 -0
- package/dist/components/siyahi/data-table-compact-columns-toggle.js +19 -0
- package/dist/components/siyahi/data-table-footnote.d.ts +12 -0
- package/dist/components/siyahi/data-table-footnote.js +35 -0
- package/dist/components/siyahi/default-sidebar-open.d.ts +8 -0
- package/dist/components/siyahi/default-sidebar-open.js +13 -0
- package/dist/components/siyahi/delta.d.ts +5 -1
- package/dist/components/siyahi/delta.js +14 -9
- package/dist/components/siyahi/drawdown-chart.d.ts +34 -0
- package/dist/components/siyahi/drawdown-chart.js +102 -0
- package/dist/components/siyahi/histogram-chart.d.ts +57 -0
- package/dist/components/siyahi/histogram-chart.js +134 -0
- package/dist/components/siyahi/page-hero.d.ts +23 -0
- package/dist/components/siyahi/page-hero.js +43 -0
- package/dist/components/siyahi/page-section.d.ts +4 -1
- package/dist/components/siyahi/page-section.js +6 -3
- package/dist/components/siyahi/page-toc.d.ts +20 -0
- package/dist/components/siyahi/page-toc.js +76 -0
- package/dist/components/siyahi/panel-grid.d.ts +24 -0
- package/dist/components/siyahi/panel-grid.js +37 -0
- package/dist/components/siyahi/quote.d.ts +12 -0
- package/dist/components/siyahi/quote.js +23 -0
- package/dist/components/siyahi/range-position.d.ts +24 -0
- package/dist/components/siyahi/range-position.js +105 -0
- package/dist/components/siyahi/scale-toggle.d.ts +32 -0
- package/dist/components/siyahi/scale-toggle.js +61 -0
- package/dist/components/siyahi/scatter-chart.d.ts +69 -0
- package/dist/components/siyahi/scatter-chart.js +395 -0
- package/dist/components/siyahi/siyahi-provider.d.ts +15 -2
- package/dist/components/siyahi/siyahi-provider.js +17 -4
- package/dist/components/siyahi/slope-chart.d.ts +35 -0
- package/dist/components/siyahi/slope-chart.js +159 -0
- package/dist/components/siyahi/stale-note.d.ts +9 -0
- package/dist/components/siyahi/stale-note.js +12 -0
- 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/target-rows.d.ts +34 -0
- package/dist/components/siyahi/target-rows.js +97 -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 +8 -5
- package/dist/components/siyahi/treemap.js +80 -34
- package/dist/components/siyahi/waterfall-chart.d.ts +51 -0
- package/dist/components/siyahi/waterfall-chart.js +147 -0
- package/dist/components/ui/accordion.js +5 -5
- package/dist/components/ui/alert.js +2 -2
- package/dist/components/ui/badge.js +1 -1
- package/dist/components/ui/breadcrumb.js +2 -2
- package/dist/components/ui/button.js +10 -10
- package/dist/components/ui/calendar.js +1 -1
- package/dist/components/ui/card.js +4 -4
- package/dist/components/ui/chart.js +1 -1
- package/dist/components/ui/code-block.js +13 -12
- package/dist/components/ui/command.js +7 -6
- package/dist/components/ui/context-menu.js +7 -7
- package/dist/components/ui/dialog.js +5 -5
- package/dist/components/ui/dropdown-menu.js +8 -8
- package/dist/components/ui/field.d.ts +26 -0
- package/dist/components/ui/field.js +109 -0
- package/dist/components/ui/input-group.js +11 -11
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/label.d.ts +5 -0
- package/dist/components/ui/label.js +13 -0
- package/dist/components/ui/popover.js +3 -3
- package/dist/components/ui/progress.js +1 -1
- package/dist/components/ui/select.js +6 -6
- package/dist/components/ui/sheet.js +5 -5
- package/dist/components/ui/sidebar.js +17 -18
- package/dist/components/ui/skeleton.js +1 -1
- package/dist/components/ui/slider.js +2 -2
- package/dist/components/ui/table.js +2 -2
- package/dist/components/ui/tabs.js +2 -2
- package/dist/components/ui/textarea.js +1 -1
- package/dist/components/ui/toggle-group.js +2 -2
- package/dist/components/ui/toggle.js +4 -4
- package/dist/components/ui/tooltip.js +2 -2
- package/dist/index.d.ts +35 -8
- package/dist/index.js +30 -4
- package/dist/lib/chart-frame.d.ts +51 -7
- package/dist/lib/chart-frame.js +390 -133
- package/dist/lib/chart-marks.d.ts +83 -0
- package/dist/lib/chart-marks.js +216 -0
- package/dist/lib/chart-series.d.ts +42 -10
- package/dist/lib/compact-columns.d.ts +19 -0
- package/dist/lib/compact-columns.js +55 -0
- package/dist/lib/fit-text.d.ts +6 -0
- package/dist/lib/fit-text.js +11 -0
- package/dist/lib/format.d.ts +8 -3
- package/dist/lib/format.js +55 -17
- package/dist/lib/heat.d.ts +7 -0
- package/dist/lib/heat.js +14 -0
- package/dist/lib/heatmap-navigation.d.ts +8 -0
- package/dist/lib/heatmap-navigation.js +49 -0
- package/dist/lib/scatter.d.ts +88 -0
- package/dist/lib/scatter.js +179 -0
- package/dist/lib/ticks.d.ts +27 -0
- package/dist/lib/ticks.js +67 -0
- package/dist/lib/tone.d.ts +36 -0
- package/dist/lib/tone.js +35 -0
- package/dist/lib/treemap.d.ts +0 -5
- package/dist/lib/treemap.js +1 -11
- package/dist/lib/use-element-width.d.ts +5 -0
- package/dist/lib/use-element-width.js +15 -0
- package/package.json +5 -1
- package/registry.lock.json +16 -0
- package/report.css +63 -47
- package/styles/siyahi.css +708 -55
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Field, FieldDescription, FieldError, FieldLabel, Input } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// A field is its label, the input and one line under it: a hint, or the error that replaces it.
|
|
4
|
+
export default function InputStatesExample() {
|
|
5
|
+
return (
|
|
6
|
+
<div className="grid max-w-sm gap-5">
|
|
7
|
+
<Field>
|
|
8
|
+
<FieldLabel htmlFor="budget">Monthly budget</FieldLabel>
|
|
9
|
+
<Input id="budget" inputMode="numeric" defaultValue="25,000" aria-describedby="budget-hint" />
|
|
10
|
+
<FieldDescription id="budget-hint">In rupees, before tax</FieldDescription>
|
|
11
|
+
</Field>
|
|
12
|
+
<Field data-invalid>
|
|
13
|
+
<FieldLabel htmlFor="pin">PIN code</FieldLabel>
|
|
14
|
+
<Input id="pin" defaultValue="56/001" aria-invalid aria-describedby="pin-error" />
|
|
15
|
+
<FieldError id="pin-error">A PIN code is six digits, such as 560001</FieldError>
|
|
16
|
+
</Field>
|
|
17
|
+
<Field data-disabled>
|
|
18
|
+
<FieldLabel htmlFor="team">Team</FieldLabel>
|
|
19
|
+
<Input id="team" defaultValue="Finance" disabled />
|
|
20
|
+
</Field>
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Input, InputGroup, InputGroupAddon, InputGroupInput, Textarea } from "@siyahi/ui";
|
|
2
|
+
import { SearchIcon } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
export default function InputExample() {
|
|
5
|
+
return (
|
|
6
|
+
<div className="flex max-w-sm flex-col gap-3">
|
|
7
|
+
<Input placeholder="Order number" aria-label="Order number" />
|
|
8
|
+
<InputGroup>
|
|
9
|
+
<InputGroupAddon>
|
|
10
|
+
<SearchIcon />
|
|
11
|
+
</InputGroupAddon>
|
|
12
|
+
<InputGroupInput placeholder="Search customers" aria-label="Search customers" />
|
|
13
|
+
</InputGroup>
|
|
14
|
+
<Textarea placeholder="Note for this order" aria-label="Note" />
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LocalTime } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
export default function LocalTimeExample() {
|
|
4
|
+
return (
|
|
5
|
+
<>
|
|
6
|
+
<p>
|
|
7
|
+
Figures as of <LocalTime value="2026-10-20T10:00:00Z" />. Hover the time to see it on your own clock.
|
|
8
|
+
</p>
|
|
9
|
+
<p>
|
|
10
|
+
Daily snapshot of <LocalTime value="2026-06-26T04:11:00Z" withDate />.
|
|
11
|
+
</p>
|
|
12
|
+
</>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { MetricStrip, ToggleGroup, ToggleGroupItem, useFormat, type MetricStripItem } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
export default function MetricStripExample() {
|
|
4
|
+
const { money, moneyCompact, pct, count } = useFormat();
|
|
5
|
+
// trend is each figure's month-end run, oldest first.
|
|
6
|
+
const items: MetricStripItem[] = [
|
|
7
|
+
{
|
|
8
|
+
label: "Revenue",
|
|
9
|
+
value: money(4512300),
|
|
10
|
+
change: 0.031,
|
|
11
|
+
note: "against September",
|
|
12
|
+
trend: [3820000, 3950000, 4110000, 4020000, 4380000, 4512300],
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
label: "Target",
|
|
16
|
+
value: moneyCompact(4025000),
|
|
17
|
+
change: 85000,
|
|
18
|
+
changeFormat: "money",
|
|
19
|
+
trend: [3600000, 3685000, 3770000, 3855000, 3940000, 4025000],
|
|
20
|
+
},
|
|
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
|
+
{
|
|
23
|
+
label: "Cash flow",
|
|
24
|
+
value: moneyCompact(-61200),
|
|
25
|
+
change: -61200,
|
|
26
|
+
changeFormat: "money",
|
|
27
|
+
trend: [14200, -3800, 9100, 2600, -18400, -61200],
|
|
28
|
+
},
|
|
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
|
+
];
|
|
32
|
+
return (
|
|
33
|
+
<MetricStrip
|
|
34
|
+
title="Revenue up 3.1% in October"
|
|
35
|
+
description="Month-end figures with the six-month run behind each"
|
|
36
|
+
action={
|
|
37
|
+
<ToggleGroup defaultValue={["1M"]} variant="outline" size="sm" aria-label="Period">
|
|
38
|
+
<ToggleGroupItem value="1M">1M</ToggleGroupItem>
|
|
39
|
+
<ToggleGroupItem value="1Y">1Y</ToggleGroupItem>
|
|
40
|
+
</ToggleGroup>
|
|
41
|
+
}
|
|
42
|
+
items={items}
|
|
43
|
+
footer={<p className="text-muted-foreground">Booked up to 31 Oct 2026</p>}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Badge,
|
|
3
|
+
Button,
|
|
4
|
+
Callout,
|
|
5
|
+
Card,
|
|
6
|
+
CardContent,
|
|
7
|
+
CardDescription,
|
|
8
|
+
CardHeader,
|
|
9
|
+
CardTitle,
|
|
10
|
+
Delta,
|
|
11
|
+
Input,
|
|
12
|
+
PageHero,
|
|
13
|
+
PanelGrid,
|
|
14
|
+
StatusBadge,
|
|
15
|
+
Table,
|
|
16
|
+
TableBody,
|
|
17
|
+
TableCell,
|
|
18
|
+
TableFooter,
|
|
19
|
+
TableHead,
|
|
20
|
+
TableHeader,
|
|
21
|
+
TableRow,
|
|
22
|
+
ToggleGroup,
|
|
23
|
+
ToggleGroupItem,
|
|
24
|
+
useFormat,
|
|
25
|
+
} from "@siyahi/ui";
|
|
26
|
+
import { DownloadIcon, LightbulbIcon, PlusIcon } from "lucide-react";
|
|
27
|
+
import { useState } from "react";
|
|
28
|
+
import ChartArea from "./chart-area";
|
|
29
|
+
import SectionCardsTrend from "./section-cards-trend";
|
|
30
|
+
|
|
31
|
+
interface Holding {
|
|
32
|
+
name: string;
|
|
33
|
+
kind: string;
|
|
34
|
+
status: string;
|
|
35
|
+
tone: "positive" | "warning" | "negative";
|
|
36
|
+
value: number;
|
|
37
|
+
change: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const holdings: Holding[] = [
|
|
41
|
+
{ name: "Nifty 50 index fund", kind: "Equity", status: "On track", tone: "positive", value: 1840000, change: 0.124 },
|
|
42
|
+
{ name: "Flexi cap fund", kind: "Equity", status: "On track", tone: "positive", value: 962000, change: 0.087 },
|
|
43
|
+
{ name: "Gold bonds, 2031", kind: "Gold", status: "Needs review", tone: "warning", value: 410500, change: 0.211 },
|
|
44
|
+
{ name: "Short-term debt fund", kind: "Debt", status: "On track", tone: "positive", value: 655000, change: 0.031 },
|
|
45
|
+
{ name: "Small cap fund", kind: "Equity", status: "Below plan", tone: "negative", value: 318200, change: -0.064 },
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
// The catalogue's own ink drop, painted with currentColor so the masthead tints it.
|
|
49
|
+
function InkDrop() {
|
|
50
|
+
return (
|
|
51
|
+
<svg viewBox="0 0 16 16">
|
|
52
|
+
<path
|
|
53
|
+
fill="currentColor"
|
|
54
|
+
fillRule="evenodd"
|
|
55
|
+
d="M8 .5C8 .5 2.5 6.3 2.5 10a5.5 5.5 0 0 0 11 0C13.5 6.3 8 .5 8 .5ZM4.75 10A3.25 3.25 0 0 0 8 13.25v-1.5A1.75 1.75 0 0 1 6.25 10Z"
|
|
56
|
+
/>
|
|
57
|
+
</svg>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function Holdings({ rows }: { rows: Holding[] }) {
|
|
62
|
+
const { money, pct } = useFormat();
|
|
63
|
+
const total = rows.reduce((sum, row) => sum + row.value, 0);
|
|
64
|
+
// The change of the whole: today's total against what the same holdings were worth a year ago.
|
|
65
|
+
const yearAgo = rows.reduce((sum, row) => sum + row.value / (1 + row.change), 0);
|
|
66
|
+
return (
|
|
67
|
+
<Card>
|
|
68
|
+
<CardHeader>
|
|
69
|
+
<CardTitle>Holdings</CardTitle>
|
|
70
|
+
<CardDescription>Value today and change over twelve months</CardDescription>
|
|
71
|
+
</CardHeader>
|
|
72
|
+
<CardContent>
|
|
73
|
+
<Table>
|
|
74
|
+
<TableHeader>
|
|
75
|
+
<TableRow>
|
|
76
|
+
<TableHead>Holding</TableHead>
|
|
77
|
+
<TableHead>Status</TableHead>
|
|
78
|
+
<TableHead data-numeric>Value</TableHead>
|
|
79
|
+
<TableHead data-numeric>Change over 12 months</TableHead>
|
|
80
|
+
</TableRow>
|
|
81
|
+
</TableHeader>
|
|
82
|
+
<TableBody>
|
|
83
|
+
{rows.length === 0 && (
|
|
84
|
+
<TableRow>
|
|
85
|
+
<TableCell colSpan={4}>
|
|
86
|
+
<span className="text-muted-foreground">No holding matches the search.</span>
|
|
87
|
+
</TableCell>
|
|
88
|
+
</TableRow>
|
|
89
|
+
)}
|
|
90
|
+
{rows.map((row) => (
|
|
91
|
+
// Only the holdings that need a look are marked; a row on track stays plain.
|
|
92
|
+
<TableRow key={row.name} data-tone={row.tone === "positive" ? undefined : row.tone}>
|
|
93
|
+
<TableCell>
|
|
94
|
+
<span className="flex flex-wrap items-center gap-2">
|
|
95
|
+
{row.name}
|
|
96
|
+
<Badge variant="outline">{row.kind}</Badge>
|
|
97
|
+
</span>
|
|
98
|
+
</TableCell>
|
|
99
|
+
<TableCell>
|
|
100
|
+
<StatusBadge tone={row.tone}>{row.status}</StatusBadge>
|
|
101
|
+
</TableCell>
|
|
102
|
+
<TableCell data-numeric>{money(row.value)}</TableCell>
|
|
103
|
+
<TableCell data-numeric>
|
|
104
|
+
<Delta value={row.change} />
|
|
105
|
+
</TableCell>
|
|
106
|
+
</TableRow>
|
|
107
|
+
))}
|
|
108
|
+
</TableBody>
|
|
109
|
+
<TableFooter>
|
|
110
|
+
<TableRow>
|
|
111
|
+
<TableCell colSpan={2}>Total</TableCell>
|
|
112
|
+
<TableCell data-numeric>{money(total)}</TableCell>
|
|
113
|
+
<TableCell data-numeric>{yearAgo > 0 && pct(total / yearAgo - 1)}</TableCell>
|
|
114
|
+
</TableRow>
|
|
115
|
+
</TableFooter>
|
|
116
|
+
</Table>
|
|
117
|
+
</CardContent>
|
|
118
|
+
</Card>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
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.
|
|
124
|
+
export default function OverviewDashboard() {
|
|
125
|
+
const [query, setQuery] = useState("");
|
|
126
|
+
const shown = holdings.filter((row) => row.name.toLowerCase().includes(query.trim().toLowerCase()));
|
|
127
|
+
return (
|
|
128
|
+
<div className="flex flex-col gap-6">
|
|
129
|
+
<PageHero
|
|
130
|
+
mark={<InkDrop />}
|
|
131
|
+
eyebrow="The Book"
|
|
132
|
+
title="Holdings"
|
|
133
|
+
lead="What you own, what it is worth today, and how each part has moved."
|
|
134
|
+
detail="Prices as of the last market close."
|
|
135
|
+
actions={
|
|
136
|
+
<>
|
|
137
|
+
<Button>
|
|
138
|
+
<PlusIcon />
|
|
139
|
+
Add a holding
|
|
140
|
+
</Button>
|
|
141
|
+
<Button variant="outline">
|
|
142
|
+
<DownloadIcon />
|
|
143
|
+
Export
|
|
144
|
+
</Button>
|
|
145
|
+
</>
|
|
146
|
+
}
|
|
147
|
+
/>
|
|
148
|
+
<div className="flex flex-wrap items-center gap-3">
|
|
149
|
+
<ToggleGroup defaultValue={["1y"]} variant="outline" aria-label="Period">
|
|
150
|
+
<ToggleGroupItem value="1m">1 month</ToggleGroupItem>
|
|
151
|
+
<ToggleGroupItem value="1y">1 year</ToggleGroupItem>
|
|
152
|
+
<ToggleGroupItem value="all">All</ToggleGroupItem>
|
|
153
|
+
</ToggleGroup>
|
|
154
|
+
<Input
|
|
155
|
+
className="w-56"
|
|
156
|
+
type="search"
|
|
157
|
+
placeholder="Search holdings"
|
|
158
|
+
aria-label="Search holdings"
|
|
159
|
+
value={query}
|
|
160
|
+
onChange={(event) => setQuery(event.target.value)}
|
|
161
|
+
/>
|
|
162
|
+
<p className="text-sm text-muted-foreground">
|
|
163
|
+
Five holdings in three kinds.{" "}
|
|
164
|
+
<a className="text-link underline underline-offset-4" href="#/data">
|
|
165
|
+
How value is worked out
|
|
166
|
+
</a>
|
|
167
|
+
</p>
|
|
168
|
+
</div>
|
|
169
|
+
<SectionCardsTrend />
|
|
170
|
+
<PanelGrid>
|
|
171
|
+
<ChartArea />
|
|
172
|
+
<Holdings rows={shown} />
|
|
173
|
+
</PanelGrid>
|
|
174
|
+
<Callout tone="accent" icon={<LightbulbIcon />} title="The takeaway">
|
|
175
|
+
Equity is <strong>74%</strong> of the book against a plan of 65%. The small cap fund is the only holding below
|
|
176
|
+
plan.
|
|
177
|
+
</Callout>
|
|
178
|
+
</div>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Button, PageHero } from "@siyahi/ui";
|
|
2
|
+
import { ArrowRightIcon } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
// The catalogue's own ink drop, painted with currentColor so the hero tints it.
|
|
5
|
+
function InkDrop() {
|
|
6
|
+
return (
|
|
7
|
+
<svg viewBox="0 0 16 16">
|
|
8
|
+
<path
|
|
9
|
+
fill="currentColor"
|
|
10
|
+
fillRule="evenodd"
|
|
11
|
+
d="M8 .5C8 .5 2.5 6.3 2.5 10a5.5 5.5 0 0 0 11 0C13.5 6.3 8 .5 8 .5ZM4.75 10A3.25 3.25 0 0 0 8 13.25v-1.5A1.75 1.75 0 0 1 6.25 10Z"
|
|
12
|
+
/>
|
|
13
|
+
</svg>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default function PageHeroExample() {
|
|
18
|
+
return (
|
|
19
|
+
<PageHero
|
|
20
|
+
eyebrow="@siyahi/ui"
|
|
21
|
+
title="Siyahi"
|
|
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
|
+
actions={
|
|
25
|
+
<>
|
|
26
|
+
<Button nativeButton={false} render={<a href="#/data" />}>
|
|
27
|
+
Browse the data components
|
|
28
|
+
<ArrowRightIcon />
|
|
29
|
+
</Button>
|
|
30
|
+
<Button variant="outline" nativeButton={false} render={<a href="#/overview/install" />}>
|
|
31
|
+
Install
|
|
32
|
+
</Button>
|
|
33
|
+
</>
|
|
34
|
+
}
|
|
35
|
+
mark={<InkDrop />}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
Card,
|
|
4
|
+
CardContent,
|
|
5
|
+
CardHeader,
|
|
6
|
+
CardTitle,
|
|
7
|
+
DataList,
|
|
8
|
+
DataListItem,
|
|
9
|
+
InlineCode,
|
|
10
|
+
PageSection,
|
|
11
|
+
PageSubheading,
|
|
12
|
+
} from "@siyahi/ui";
|
|
13
|
+
import { ArrowDownIcon } from "lucide-react";
|
|
14
|
+
|
|
15
|
+
export default function PageSectionExample() {
|
|
16
|
+
return (
|
|
17
|
+
<PageSection
|
|
18
|
+
id="toolkit"
|
|
19
|
+
eyebrow="Part 2"
|
|
20
|
+
title="The toolkit"
|
|
21
|
+
lead={
|
|
22
|
+
<p>
|
|
23
|
+
One command, <InlineCode>vp</InlineCode>, builds, tests and lints; it replaces the separate config of each.
|
|
24
|
+
</p>
|
|
25
|
+
}
|
|
26
|
+
action={
|
|
27
|
+
<Button variant="outline" size="sm">
|
|
28
|
+
<ArrowDownIcon data-icon="inline-start" />
|
|
29
|
+
Skip to the commands
|
|
30
|
+
</Button>
|
|
31
|
+
}
|
|
32
|
+
>
|
|
33
|
+
<PageSubheading>What each tool does</PageSubheading>
|
|
34
|
+
<Card>
|
|
35
|
+
<CardHeader>
|
|
36
|
+
<CardTitle>Vite+</CardTitle>
|
|
37
|
+
</CardHeader>
|
|
38
|
+
<CardContent>
|
|
39
|
+
<DataList>
|
|
40
|
+
<DataListItem label="In Java terms">Maven, the compiler plugin and Surefire in one binary.</DataListItem>
|
|
41
|
+
<DataListItem label="How it is set up">
|
|
42
|
+
One <InlineCode>vite.config.ts</InlineCode> at the root of the repo.
|
|
43
|
+
</DataListItem>
|
|
44
|
+
<DataListItem label="Remember">
|
|
45
|
+
<InlineCode>vp check</InlineCode>
|
|
46
|
+
</DataListItem>
|
|
47
|
+
</DataList>
|
|
48
|
+
</CardContent>
|
|
49
|
+
</Card>
|
|
50
|
+
</PageSection>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
Popover,
|
|
4
|
+
PopoverContent,
|
|
5
|
+
PopoverDescription,
|
|
6
|
+
PopoverHeader,
|
|
7
|
+
PopoverTitle,
|
|
8
|
+
PopoverTrigger,
|
|
9
|
+
} from "@siyahi/ui";
|
|
10
|
+
|
|
11
|
+
export default function PopoverExample() {
|
|
12
|
+
return (
|
|
13
|
+
<Popover>
|
|
14
|
+
<PopoverTrigger render={<Button variant="outline" className="w-fit" />}>How is this counted?</PopoverTrigger>
|
|
15
|
+
<PopoverContent align="start">
|
|
16
|
+
<PopoverHeader>
|
|
17
|
+
<PopoverTitle>Paid orders</PopoverTitle>
|
|
18
|
+
<PopoverDescription>Revenue counts paid orders, less refunds, on the day each was placed.</PopoverDescription>
|
|
19
|
+
</PopoverHeader>
|
|
20
|
+
</PopoverContent>
|
|
21
|
+
</Popover>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, PriceChart } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// A made-up daily series for one year: the average order value, in rupees.
|
|
4
|
+
const data = Array.from({ length: 250 }, (_, i) => {
|
|
5
|
+
const day = new Date(Date.UTC(2025, 9, 20 + Math.floor((i * 7) / 5)));
|
|
6
|
+
return { time: day.toISOString().slice(0, 10), value: 1500 + i * 1.2 + Math.sin(i / 9) * 60 + Math.sin(i / 3) * 18 };
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export default function PriceChartExample() {
|
|
10
|
+
return (
|
|
11
|
+
<Card>
|
|
12
|
+
<CardHeader>
|
|
13
|
+
<CardTitle>Average order value</CardTitle>
|
|
14
|
+
<CardDescription>Daily, one year, ₹</CardDescription>
|
|
15
|
+
</CardHeader>
|
|
16
|
+
<CardContent>
|
|
17
|
+
<PriceChart data={data} height={256} />
|
|
18
|
+
</CardContent>
|
|
19
|
+
<CardFooter>
|
|
20
|
+
<span className="text-xs text-muted-foreground">
|
|
21
|
+
Chart by{" "}
|
|
22
|
+
<a
|
|
23
|
+
className="text-link underline-offset-4 hover:underline"
|
|
24
|
+
href="https://www.tradingview.com/lightweight-charts/"
|
|
25
|
+
>
|
|
26
|
+
TradingView Lightweight Charts
|
|
27
|
+
</a>
|
|
28
|
+
</span>
|
|
29
|
+
</CardFooter>
|
|
30
|
+
</Card>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ToneProgress, useFormat } from "@siyahi/ui";
|
|
2
|
+
|
|
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 },
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
export default function ProgressToneExample() {
|
|
11
|
+
const { pct } = useFormat();
|
|
12
|
+
return (
|
|
13
|
+
<div className="flex max-w-sm flex-col gap-3 text-sm">
|
|
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>
|
|
17
|
+
<ToneProgress
|
|
18
|
+
tone={p.profit >= 0 ? "positive" : "negative"}
|
|
19
|
+
value={p.share * 100}
|
|
20
|
+
aria-label={`${p.channel}'s share of the quarter's profit and loss`}
|
|
21
|
+
getAriaValueText={() => pct(p.share)}
|
|
22
|
+
className="w-24"
|
|
23
|
+
/>
|
|
24
|
+
<span className="tabular-nums">{pct(p.share)}</span>
|
|
25
|
+
</div>
|
|
26
|
+
))}
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Progress, ProgressLabel, ProgressValue } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
export default function ProgressExample() {
|
|
4
|
+
return (
|
|
5
|
+
<Progress value={64} className="max-w-sm">
|
|
6
|
+
<ProgressLabel>Orders imported</ProgressLabel>
|
|
7
|
+
<ProgressValue />
|
|
8
|
+
</Progress>
|
|
9
|
+
);
|
|
10
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Card,
|
|
3
|
+
CardContent,
|
|
4
|
+
CardDescription,
|
|
5
|
+
CardHeader,
|
|
6
|
+
CardTitle,
|
|
7
|
+
DataTable,
|
|
8
|
+
DataTableBody,
|
|
9
|
+
DataTableCompactColumnsToggle,
|
|
10
|
+
DataTableHeader,
|
|
11
|
+
DataTableRoot,
|
|
12
|
+
DataTableSortHeader,
|
|
13
|
+
DataTableToolbarSection,
|
|
14
|
+
RangePosition,
|
|
15
|
+
useFormat,
|
|
16
|
+
type DataTableColumnDef,
|
|
17
|
+
} from "@siyahi/ui";
|
|
18
|
+
|
|
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
|
+
low: number;
|
|
24
|
+
high: number;
|
|
25
|
+
/** How far up its range today sits, 0 at the fastest day and 1 at the slowest, so the column sorts. */
|
|
26
|
+
position: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const service = (name: string, today: number, low: number, high: number): Service => ({
|
|
30
|
+
service: name,
|
|
31
|
+
today,
|
|
32
|
+
low,
|
|
33
|
+
high,
|
|
34
|
+
position: (today - low) / (high - low),
|
|
35
|
+
});
|
|
36
|
+
|
|
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
|
+
];
|
|
45
|
+
|
|
46
|
+
function useMilliseconds(): (value: number) => string {
|
|
47
|
+
const { count } = useFormat();
|
|
48
|
+
return (value) => `${count(value)} ms`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function Milliseconds({ value }: { value: number }) {
|
|
52
|
+
return useMilliseconds()(value);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function Range({ row }: { row: Service }) {
|
|
56
|
+
const ms = useMilliseconds();
|
|
57
|
+
return (
|
|
58
|
+
<RangePosition
|
|
59
|
+
variant="compact"
|
|
60
|
+
low={row.low}
|
|
61
|
+
high={row.high}
|
|
62
|
+
value={row.today}
|
|
63
|
+
valueFormatter={ms}
|
|
64
|
+
lowLabel="30-day fastest"
|
|
65
|
+
highLabel="30-day slowest"
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const header = () => <DataTableSortHeader />;
|
|
71
|
+
|
|
72
|
+
const columns: DataTableColumnDef<Service>[] = [
|
|
73
|
+
{ accessorKey: "service", header, size: 130, meta: { label: "Service", compact: true } },
|
|
74
|
+
{
|
|
75
|
+
accessorKey: "today",
|
|
76
|
+
header,
|
|
77
|
+
size: 170,
|
|
78
|
+
meta: { label: "95th percentile today", variant: "number" },
|
|
79
|
+
cell: ({ row }) => <Milliseconds value={row.original.today} />,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
accessorKey: "position",
|
|
83
|
+
header,
|
|
84
|
+
size: 200,
|
|
85
|
+
meta: { label: "30-day range", compact: true },
|
|
86
|
+
cell: ({ row }) => <Range row={row.original} />,
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
export default function RangePositionTableExample() {
|
|
91
|
+
return (
|
|
92
|
+
<Card>
|
|
93
|
+
<CardHeader>
|
|
94
|
+
<CardTitle>Search is near its slowest of the month, login near its fastest</CardTitle>
|
|
95
|
+
<CardDescription>
|
|
96
|
+
Each service's 95th-percentile response time today (95 in 100 requests were faster) on a track from its
|
|
97
|
+
fastest day to its slowest; sort to rank them
|
|
98
|
+
</CardDescription>
|
|
99
|
+
</CardHeader>
|
|
100
|
+
<CardContent>
|
|
101
|
+
<DataTableRoot data={services} columns={columns}>
|
|
102
|
+
<DataTableToolbarSection>
|
|
103
|
+
<DataTableCompactColumnsToggle />
|
|
104
|
+
</DataTableToolbarSection>
|
|
105
|
+
<DataTable aria-label="Services in their 30-day range">
|
|
106
|
+
<DataTableHeader />
|
|
107
|
+
<DataTableBody />
|
|
108
|
+
</DataTable>
|
|
109
|
+
</DataTableRoot>
|
|
110
|
+
</CardContent>
|
|
111
|
+
</Card>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Card,
|
|
3
|
+
CardContent,
|
|
4
|
+
CardDescription,
|
|
5
|
+
CardHeader,
|
|
6
|
+
CardTitle,
|
|
7
|
+
DataList,
|
|
8
|
+
DataListItem,
|
|
9
|
+
RangePosition,
|
|
10
|
+
useFormat,
|
|
11
|
+
} from "@siyahi/ui";
|
|
12
|
+
|
|
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
|
+
|
|
18
|
+
export default function RangePositionExample() {
|
|
19
|
+
const f = useFormat();
|
|
20
|
+
const ms = (value: number) => `${f.count(value)} ms`;
|
|
21
|
+
return (
|
|
22
|
+
// Side by side once the card, not the screen, has room: in a narrow panel on a wide screen they stack.
|
|
23
|
+
<Card className="@container/range">
|
|
24
|
+
<CardHeader>
|
|
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
|
+
</CardHeader>
|
|
28
|
+
<CardContent>
|
|
29
|
+
<div className="flex flex-col gap-8 @xl/range:flex-row @xl/range:items-end">
|
|
30
|
+
<DataList className="@xl/range:w-56 @xl/range:shrink-0">
|
|
31
|
+
<DataListItem label="Fastest day, 3 weeks ago">
|
|
32
|
+
<span className="tabular-nums">{ms(low)}</span>
|
|
33
|
+
</DataListItem>
|
|
34
|
+
<DataListItem label="Slowest day, 9 days ago">
|
|
35
|
+
<span className="tabular-nums">{ms(high)}</span>
|
|
36
|
+
</DataListItem>
|
|
37
|
+
<DataListItem label="Today, 95th percentile">
|
|
38
|
+
<span className="tabular-nums">{ms(today)}</span>
|
|
39
|
+
</DataListItem>
|
|
40
|
+
</DataList>
|
|
41
|
+
<RangePosition
|
|
42
|
+
low={low}
|
|
43
|
+
high={high}
|
|
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
|
+
className="@xl/range:flex-1"
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
</CardContent>
|
|
53
|
+
</Card>
|
|
54
|
+
);
|
|
55
|
+
}
|