@siyahi/ui 0.1.9-next.3 → 0.1.9-next.30
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 +170 -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 +42 -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 +40 -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 +108 -0
- package/agents/examples/data-table-compact.tsx +96 -0
- package/agents/examples/data-table-filters.tsx +103 -0
- package/agents/examples/data-table.tsx +99 -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 +101 -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,28 @@
|
|
|
1
|
+
import { BarChartCard } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// Opening hours in IST; each row is the hour an order was placed in.
|
|
4
|
+
const data = [
|
|
5
|
+
{ hour: 9, orders: 42 },
|
|
6
|
+
{ hour: 10, orders: 31 },
|
|
7
|
+
{ hour: 11, orders: 18 },
|
|
8
|
+
{ hour: 12, orders: 12 },
|
|
9
|
+
{ hour: 13, orders: 15 },
|
|
10
|
+
{ hour: 14, orders: 24 },
|
|
11
|
+
{ hour: 15, orders: 38 },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export default function ChartBarHourlyExample() {
|
|
15
|
+
return (
|
|
16
|
+
<BarChartCard
|
|
17
|
+
title="Orders by hour"
|
|
18
|
+
description="Last 30 days, by the hour each order was placed"
|
|
19
|
+
data={data}
|
|
20
|
+
xKey="hour"
|
|
21
|
+
xFormatter={(hour) => `${String(hour).padStart(2, "0")}:00`}
|
|
22
|
+
xLabel="Hour of day (IST)"
|
|
23
|
+
yLabel="Orders"
|
|
24
|
+
series={[{ key: "orders", label: "Orders", color: "var(--chart-1)" }]}
|
|
25
|
+
height={256}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BarChartCard, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// A new product line's operating result per financial year, a loss every year; made-up figures.
|
|
4
|
+
const data = [
|
|
5
|
+
{ fy: "FY23", net: -48000 },
|
|
6
|
+
{ fy: "FY24", net: -91000 },
|
|
7
|
+
{ fy: "FY25", net: -27000 },
|
|
8
|
+
{ fy: "FY26", net: -63000 },
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
const series: ChartSeries<(typeof data)[number]> = [
|
|
12
|
+
{ key: "net", label: "Operating result", color: "var(--positive)", negativeColor: "var(--negative)" },
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
export default function ChartBarLossesExample() {
|
|
16
|
+
const { money, moneyCompact } = useFormat();
|
|
17
|
+
return (
|
|
18
|
+
<BarChartCard
|
|
19
|
+
title="Operating loss by financial year"
|
|
20
|
+
description="A loss every year, so every bar runs down from zero"
|
|
21
|
+
data={data}
|
|
22
|
+
xKey="fy"
|
|
23
|
+
series={series}
|
|
24
|
+
valueFormatter={money}
|
|
25
|
+
yTickFormatter={moneyCompact}
|
|
26
|
+
height={240}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { BarChartCard, ToggleGroup, ToggleGroupItem, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
3
|
+
|
|
4
|
+
// Each team's share of this year's spend against a comparison; made-up figures.
|
|
5
|
+
const SHARES = {
|
|
6
|
+
Plan: [
|
|
7
|
+
{ team: "Engineering and Infrastructure", actual: 0.34, comparison: 0.37 },
|
|
8
|
+
{ team: "Sales and Business Development", actual: 0.21, comparison: 0.13 },
|
|
9
|
+
{ team: "Finance, Legal & Compliance", actual: 0.06, comparison: 0.1 },
|
|
10
|
+
{ team: "Marketing and Communications", actual: 0.12, comparison: 0.08 },
|
|
11
|
+
{ team: "Customer Support and Success", actual: 0.09, comparison: 0.07 },
|
|
12
|
+
{ team: "Operations", actual: 0.08, comparison: 0.04 },
|
|
13
|
+
],
|
|
14
|
+
"Last year": [
|
|
15
|
+
{ team: "Engineering and Infrastructure", actual: 0.34, comparison: 0.31 },
|
|
16
|
+
{ team: "Sales and Business Development", actual: 0.21, comparison: 0.1 },
|
|
17
|
+
{ team: "Finance, Legal & Compliance", actual: 0.06, comparison: 0.08 },
|
|
18
|
+
{ team: "Marketing and Communications", actual: 0.12, comparison: 0.07 },
|
|
19
|
+
{ team: "Customer Support and Success", actual: 0.09, comparison: 0.07 },
|
|
20
|
+
{ team: "Operations", actual: 0.08, comparison: 0.06 },
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
type Comparison = keyof typeof SHARES;
|
|
24
|
+
type Row = (typeof SHARES)[Comparison][number];
|
|
25
|
+
|
|
26
|
+
export default function ChartBarTeamsExample() {
|
|
27
|
+
const { pct } = useFormat();
|
|
28
|
+
const [comparison, setComparison] = useState<Comparison>("Plan");
|
|
29
|
+
const rows = SHARES[comparison];
|
|
30
|
+
const series: ChartSeries<Row> = [
|
|
31
|
+
{ key: "actual", label: "This year", color: "var(--chart-1)" },
|
|
32
|
+
{ key: "comparison", label: comparison, color: "var(--chart-2)" },
|
|
33
|
+
];
|
|
34
|
+
const gap = (row: Row) => {
|
|
35
|
+
const points = Math.abs(row.actual - row.comparison) * 100;
|
|
36
|
+
return row.actual >= row.comparison ? `+${points.toFixed(1)} pts over` : `\u2212${points.toFixed(1)} pts under`;
|
|
37
|
+
};
|
|
38
|
+
return (
|
|
39
|
+
<BarChartCard
|
|
40
|
+
title="Spend by team against plan or last year"
|
|
41
|
+
description="Each team's share of this year's spend and of the comparison"
|
|
42
|
+
action={
|
|
43
|
+
<ToggleGroup
|
|
44
|
+
value={[comparison]}
|
|
45
|
+
onValueChange={([next]) => {
|
|
46
|
+
// Pressing the selected comparison again would leave none selected; keep it.
|
|
47
|
+
if (next) setComparison(next as Comparison);
|
|
48
|
+
}}
|
|
49
|
+
variant="outline"
|
|
50
|
+
size="sm"
|
|
51
|
+
aria-label="Compare with"
|
|
52
|
+
>
|
|
53
|
+
<ToggleGroupItem value="Plan">Plan</ToggleGroupItem>
|
|
54
|
+
<ToggleGroupItem value="Last year">Last year</ToggleGroupItem>
|
|
55
|
+
</ToggleGroup>
|
|
56
|
+
}
|
|
57
|
+
horizontal
|
|
58
|
+
data={rows}
|
|
59
|
+
xKey="team"
|
|
60
|
+
xTickDetail={(row) => `${pct(row.actual)} vs ${pct(row.comparison)} · ${gap(row)}`}
|
|
61
|
+
series={series}
|
|
62
|
+
valueFormatter={(v) => pct(v)}
|
|
63
|
+
// A tick format puts the value axis along the bottom of the sideways bars.
|
|
64
|
+
yTickFormatter={(v) => pct(v, 0)}
|
|
65
|
+
// Sideways, y is still the value: the axis runs 0 to 40% and the cap is a value level.
|
|
66
|
+
yDomain={[0, 0.4]}
|
|
67
|
+
referenceLines={[{ y: 0.3, label: "cap 30%", labelPosition: "insideBottomRight" }]}
|
|
68
|
+
height={rows.length * 56 + 48}
|
|
69
|
+
footer={<p className="text-muted-foreground">Salaries are left out; they are budgeted separately.</p>}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { BarChartCard, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
3
|
+
|
|
4
|
+
// Net profit per financial year (April to March); made-up figures.
|
|
5
|
+
const data = [
|
|
6
|
+
{ fy: "FY22", net: 142000 },
|
|
7
|
+
{ fy: "FY23", net: 186000 },
|
|
8
|
+
{ fy: "FY24", net: -164000 },
|
|
9
|
+
{ fy: "FY25", net: 128000 },
|
|
10
|
+
{ fy: "FY26", net: -121000 },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
// A gain and a loss take the meaning colours; the arrow in each tick says the same without colour.
|
|
14
|
+
const series: ChartSeries<(typeof data)[number]> = [
|
|
15
|
+
{ key: "net", label: "Net profit", color: "var(--positive)", negativeColor: "var(--negative)" },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
export default function ChartBarYearsExample() {
|
|
19
|
+
const { money, moneyCompact } = useFormat();
|
|
20
|
+
// The page owns the pick, so it can narrow the rest of the page to that year.
|
|
21
|
+
const [year, setYear] = useState<string | null>(null);
|
|
22
|
+
const signed = (v: number) => `${v < 0 ? "\u2212" : "+"}${moneyCompact(Math.abs(v))}`;
|
|
23
|
+
return (
|
|
24
|
+
<BarChartCard
|
|
25
|
+
title="Profit by financial year"
|
|
26
|
+
description={
|
|
27
|
+
year ? `${year} picked; click it again for every year` : "April to March, before tax. Click a year to pick it."
|
|
28
|
+
}
|
|
29
|
+
data={data}
|
|
30
|
+
xKey="fy"
|
|
31
|
+
xTickDetail={(row) => signed(row.net)}
|
|
32
|
+
selected={year}
|
|
33
|
+
onSelect={setYear}
|
|
34
|
+
series={series}
|
|
35
|
+
valueFormatter={money}
|
|
36
|
+
yTickFormatter={moneyCompact}
|
|
37
|
+
height={272}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { BarChartCard, ToggleGroup, ToggleGroupItem, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
3
|
+
|
|
4
|
+
const data = [
|
|
5
|
+
{ quarter: "Q1", online: 120000, retail: 40000, wholesale: 15000, marketplace: 9000, events: 4000 },
|
|
6
|
+
{ quarter: "Q2", online: 95000, retail: 52000, wholesale: 20000, marketplace: 6000, events: 3000 },
|
|
7
|
+
{ quarter: "Q3", online: 140000, retail: 38000, wholesale: 12000, marketplace: 11000, events: 5000 },
|
|
8
|
+
{ quarter: "Q4", online: 160000, retail: 45000, wholesale: 25000, marketplace: 7000, events: 2000 },
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
// Series take the slots in order: neighbours differ in lightness, slots two
|
|
12
|
+
// apart differ in hue.
|
|
13
|
+
const series: ChartSeries<(typeof data)[number]> = [
|
|
14
|
+
{ key: "online", label: "Online", color: "var(--chart-1)" },
|
|
15
|
+
{ key: "retail", label: "Retail", color: "var(--chart-2)" },
|
|
16
|
+
{ key: "wholesale", label: "Wholesale", color: "var(--chart-3)" },
|
|
17
|
+
{ key: "marketplace", label: "Marketplace", color: "var(--chart-4)" },
|
|
18
|
+
{ key: "events", label: "Events", color: "var(--chart-5)" },
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
export default function ChartBarExample() {
|
|
22
|
+
const { money, moneyCompact } = useFormat();
|
|
23
|
+
const [layout, setLayout] = useState("grouped");
|
|
24
|
+
return (
|
|
25
|
+
<BarChartCard
|
|
26
|
+
title="Revenue by channel and quarter"
|
|
27
|
+
description={
|
|
28
|
+
layout === "grouped"
|
|
29
|
+
? "All five chart colours side by side, in series order"
|
|
30
|
+
: "All five chart colours stacked into the quarter's total"
|
|
31
|
+
}
|
|
32
|
+
action={
|
|
33
|
+
<ToggleGroup
|
|
34
|
+
value={[layout]}
|
|
35
|
+
onValueChange={([next]) => {
|
|
36
|
+
// Pressing the selected layout again would leave none selected; keep it.
|
|
37
|
+
if (next) setLayout(next);
|
|
38
|
+
}}
|
|
39
|
+
variant="outline"
|
|
40
|
+
size="sm"
|
|
41
|
+
aria-label="Layout"
|
|
42
|
+
>
|
|
43
|
+
<ToggleGroupItem value="grouped">Grouped</ToggleGroupItem>
|
|
44
|
+
<ToggleGroupItem value="stacked">Stacked</ToggleGroupItem>
|
|
45
|
+
</ToggleGroup>
|
|
46
|
+
}
|
|
47
|
+
data={data}
|
|
48
|
+
xKey="quarter"
|
|
49
|
+
series={series}
|
|
50
|
+
stacked={layout === "stacked"}
|
|
51
|
+
valueFormatter={money}
|
|
52
|
+
yTickFormatter={moneyCompact}
|
|
53
|
+
height={256}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { AreaChartCard, BarChartCard, LineChartCard, type SeriesChartProps } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
const data = Array.from({ length: 84 }, (_, index) => ({
|
|
4
|
+
month: `${2019 + Math.floor(index / 12)}-${String((index % 12) + 1).padStart(2, "0")}`,
|
|
5
|
+
orders: 20 + ((index * 7) % 31),
|
|
6
|
+
}));
|
|
7
|
+
const props: SeriesChartProps<(typeof data)[number], "month"> = {
|
|
8
|
+
title: "Monthly orders, bars",
|
|
9
|
+
description: "Demo orders per month, 2019–2025; only April is labelled",
|
|
10
|
+
data,
|
|
11
|
+
xKey: "month",
|
|
12
|
+
xTicks: data.filter(({ month }) => month.endsWith("-04")).map(({ month }) => month),
|
|
13
|
+
xFormatter: (month) => `Apr ${month.slice(2, 4)}`,
|
|
14
|
+
xTooltipFormatter: (month) => month,
|
|
15
|
+
series: [{ key: "orders", label: "Orders", color: "var(--chart-1)" }],
|
|
16
|
+
height: 200,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default function ChartCategoryTicksExample() {
|
|
20
|
+
return (
|
|
21
|
+
<div className="flex flex-col gap-4">
|
|
22
|
+
<BarChartCard {...props} />
|
|
23
|
+
<BarChartCard
|
|
24
|
+
{...props}
|
|
25
|
+
title="Monthly orders, sideways"
|
|
26
|
+
description="Demo orders per month in 2019; only April is labelled"
|
|
27
|
+
data={data.slice(0, 12)}
|
|
28
|
+
xTicks={["2019-04"]}
|
|
29
|
+
horizontal
|
|
30
|
+
height={300}
|
|
31
|
+
/>
|
|
32
|
+
<BarChartCard
|
|
33
|
+
title="Orders by category"
|
|
34
|
+
description="Demo orders; one long category label on a narrow chart"
|
|
35
|
+
data={[
|
|
36
|
+
{ category: "Home Appliances and Kitchen Equipment", orders: 100 },
|
|
37
|
+
{ category: "Other", orders: 50 },
|
|
38
|
+
{ category: "Third", orders: 70 },
|
|
39
|
+
]}
|
|
40
|
+
xKey="category"
|
|
41
|
+
xTicks={["Home Appliances and Kitchen Equipment"]}
|
|
42
|
+
series={[{ key: "orders", label: "Orders", color: "var(--chart-1)" }]}
|
|
43
|
+
horizontal
|
|
44
|
+
height={220}
|
|
45
|
+
/>
|
|
46
|
+
<LineChartCard {...props} title="Monthly orders, line" />
|
|
47
|
+
<AreaChartCard {...props} title="Monthly orders, area" />
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { LineChartCard, type ChartSeries } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// A sample every 15 s from 19:33:58; the numbers are made up for the catalogue.
|
|
4
|
+
const START = (19 * 60 + 33) * 60 + 58;
|
|
5
|
+
const PRESSURE = [
|
|
6
|
+
4, 18, 41, 58, 63, 66, 61, 70, 72, 68, 64, 71, 74, 69, 66, 62, 67, 73, 70, 65, 68, 71, 66, 63, 69, 72,
|
|
7
|
+
];
|
|
8
|
+
const data = PRESSURE.map((pressure, i) => ({ second: i * 15, pressure }));
|
|
9
|
+
|
|
10
|
+
const series: ChartSeries<(typeof data)[number]> = [
|
|
11
|
+
{ key: "pressure", label: "Full pressure", color: "var(--chart-1)" },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const pad = (n: number) => String(n).padStart(2, "0");
|
|
15
|
+
|
|
16
|
+
function clock(second: number) {
|
|
17
|
+
const t = START + second;
|
|
18
|
+
return `${Math.floor(t / 3600)}:${pad(Math.floor(t / 60) % 60)}:${pad(t % 60)}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default function ChartLineEventsExample() {
|
|
22
|
+
return (
|
|
23
|
+
<LineChartCard
|
|
24
|
+
title="Memory pressure of a test group, %"
|
|
25
|
+
description="avg10, sampled every 15 s"
|
|
26
|
+
data={data}
|
|
27
|
+
xKey="second"
|
|
28
|
+
// A numeric axis: ticks fall on whole minutes, 2 s after the first sample.
|
|
29
|
+
xDomain={[0, 390]}
|
|
30
|
+
xTicks={[2, 62, 122, 182, 242, 302, 362]}
|
|
31
|
+
xFormatter={(second) => clock(second).slice(0, 5)}
|
|
32
|
+
xTooltipFormatter={(second) => `${clock(second)} IST, 10 s average`}
|
|
33
|
+
series={series}
|
|
34
|
+
curve="linear"
|
|
35
|
+
valueFormatter={(v) => `${v}%`}
|
|
36
|
+
yDomain={[0, 100]}
|
|
37
|
+
yTicks={[0, 25, 50, 75, 100]}
|
|
38
|
+
referenceLines={[
|
|
39
|
+
{ y: 80, label: "old limit, 80%" },
|
|
40
|
+
{ y: 50, label: "new limit, 50%", emphasis: "strong" },
|
|
41
|
+
{ x: 313, label: "limit 50%", labelPosition: "insideBottomRight" },
|
|
42
|
+
{ x: 367, label: "killed", emphasis: "strong", labelPosition: "insideTopRight" },
|
|
43
|
+
]}
|
|
44
|
+
height={224}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { LineChartCard, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// Net worth's growth against the plan since May; November and December are a forecast.
|
|
4
|
+
const worth = [
|
|
5
|
+
{ month: "May", actual: 0, plan: 0 },
|
|
6
|
+
{ month: "Jun", actual: 0.025, plan: 0.022 },
|
|
7
|
+
{ month: "Jul", actual: 0.061, plan: 0.044 },
|
|
8
|
+
{ month: "Aug", actual: 0.047, plan: 0.067 },
|
|
9
|
+
{ month: "Sep", actual: 0.11, plan: 0.089 },
|
|
10
|
+
{ month: "Oct", actual: 0.156, plan: 0.111 },
|
|
11
|
+
{ month: "Nov", actual: 0.177, plan: 0.133 },
|
|
12
|
+
{ month: "Dec", actual: 0.202, plan: 0.156 },
|
|
13
|
+
];
|
|
14
|
+
const series: ChartSeries<(typeof worth)[number]> = [
|
|
15
|
+
{ key: "actual", label: "Net worth", color: "var(--chart-1)" },
|
|
16
|
+
{ key: "plan", label: "Plan", color: "var(--chart-2)" },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
// Today is a rule in the link colour; from forecastFrom the lines dash, a hatched band covers the stretch and the end
|
|
20
|
+
// dots are hollow.
|
|
21
|
+
export default function ChartLineForecastExample() {
|
|
22
|
+
const { pct } = useFormat();
|
|
23
|
+
return (
|
|
24
|
+
<LineChartCard
|
|
25
|
+
title="Growth against plan"
|
|
26
|
+
description="Since May, month-end; November and December are a forecast"
|
|
27
|
+
data={worth}
|
|
28
|
+
xKey="month"
|
|
29
|
+
series={series}
|
|
30
|
+
today="Oct"
|
|
31
|
+
forecastFrom="Oct"
|
|
32
|
+
valueFormatter={pct}
|
|
33
|
+
height={256}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Badge, LineChartCard, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// Monthly active users in the app's first year, made up for the catalogue: from a few hundred to tens of thousands.
|
|
4
|
+
const data = [
|
|
5
|
+
{ month: "Nov", users: 240 },
|
|
6
|
+
{ month: "Dec", users: 410 },
|
|
7
|
+
{ month: "Jan", users: 780 },
|
|
8
|
+
{ month: "Feb", users: 1350 },
|
|
9
|
+
{ month: "Mar", users: 2100 },
|
|
10
|
+
{ month: "Apr", users: 3900 },
|
|
11
|
+
{ month: "May", users: 6200 },
|
|
12
|
+
{ month: "Jun", users: 9800 },
|
|
13
|
+
{ month: "Jul", users: 14100 },
|
|
14
|
+
{ month: "Aug", users: 21500 },
|
|
15
|
+
{ month: "Sep", users: 30200 },
|
|
16
|
+
{ month: "Oct", users: 46800 },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const series: ChartSeries<(typeof data)[number]> = [{ key: "users", label: "Active users", color: "var(--chart-1)" }];
|
|
20
|
+
|
|
21
|
+
export default function ChartLineLogExample() {
|
|
22
|
+
const { count } = useFormat();
|
|
23
|
+
return (
|
|
24
|
+
<LineChartCard
|
|
25
|
+
title="Active users grew about 1.5× a month all year"
|
|
26
|
+
description="On log, steady growth is a straight line; Linear shows how much of it came in the last few months."
|
|
27
|
+
action={<Badge variant="outline">First year</Badge>}
|
|
28
|
+
data={data}
|
|
29
|
+
xKey="month"
|
|
30
|
+
series={series}
|
|
31
|
+
// Log is selected first; the buttons in the header let the reader switch.
|
|
32
|
+
yScale="log"
|
|
33
|
+
yScaleToggle
|
|
34
|
+
yLabel="Active users"
|
|
35
|
+
valueFormatter={count}
|
|
36
|
+
height={256}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { LineChartCard, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// Eight funds' month-end growth; November and December are a forecast.
|
|
4
|
+
const growth = [
|
|
5
|
+
{ month: "May", flexi: 0, debt: 0, small: 0, intl: 0, liquid: 0, midcap: 0, nifty: 0, gold: 0 },
|
|
6
|
+
{
|
|
7
|
+
month: "Jun",
|
|
8
|
+
flexi: 0.018,
|
|
9
|
+
debt: 0.006,
|
|
10
|
+
small: 0.034,
|
|
11
|
+
intl: 0.012,
|
|
12
|
+
liquid: 0.005,
|
|
13
|
+
midcap: 0.022,
|
|
14
|
+
nifty: 0.025,
|
|
15
|
+
gold: 0.041,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
month: "Jul",
|
|
19
|
+
flexi: 0.049,
|
|
20
|
+
debt: 0.013,
|
|
21
|
+
small: 0.012,
|
|
22
|
+
intl: 0.038,
|
|
23
|
+
liquid: 0.011,
|
|
24
|
+
midcap: 0.03,
|
|
25
|
+
nifty: 0.061,
|
|
26
|
+
gold: 0.072,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
month: "Aug",
|
|
30
|
+
flexi: 0.058,
|
|
31
|
+
debt: 0.02,
|
|
32
|
+
small: -0.041,
|
|
33
|
+
intl: 0.066,
|
|
34
|
+
liquid: 0.017,
|
|
35
|
+
midcap: 0.011,
|
|
36
|
+
nifty: 0.047,
|
|
37
|
+
gold: 0.118,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
month: "Sep",
|
|
41
|
+
flexi: 0.094,
|
|
42
|
+
debt: 0.027,
|
|
43
|
+
small: -0.018,
|
|
44
|
+
intl: 0.081,
|
|
45
|
+
liquid: 0.023,
|
|
46
|
+
midcap: 0.052,
|
|
47
|
+
nifty: 0.11,
|
|
48
|
+
gold: 0.153,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
month: "Oct",
|
|
52
|
+
flexi: 0.141,
|
|
53
|
+
debt: 0.034,
|
|
54
|
+
small: -0.052,
|
|
55
|
+
intl: 0.119,
|
|
56
|
+
liquid: 0.029,
|
|
57
|
+
midcap: 0.078,
|
|
58
|
+
nifty: 0.156,
|
|
59
|
+
gold: 0.196,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
month: "Nov",
|
|
63
|
+
flexi: 0.166,
|
|
64
|
+
debt: 0.043,
|
|
65
|
+
small: -0.04,
|
|
66
|
+
intl: 0.142,
|
|
67
|
+
liquid: 0.037,
|
|
68
|
+
midcap: 0.099,
|
|
69
|
+
nifty: 0.177,
|
|
70
|
+
gold: 0.221,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
month: "Dec",
|
|
74
|
+
flexi: 0.189,
|
|
75
|
+
debt: 0.052,
|
|
76
|
+
small: -0.031,
|
|
77
|
+
intl: 0.164,
|
|
78
|
+
liquid: 0.046,
|
|
79
|
+
midcap: 0.12,
|
|
80
|
+
nifty: 0.202,
|
|
81
|
+
gold: 0.245,
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
// The palette has five colours, so past five the page names the few it is about in colour; the rest are muted, draw
|
|
86
|
+
// first in grey, each still named at its end.
|
|
87
|
+
const QUIET = "var(--muted-foreground)";
|
|
88
|
+
const series: ChartSeries<(typeof growth)[number]> = [
|
|
89
|
+
{ key: "flexi", label: "Flexi cap", color: QUIET },
|
|
90
|
+
{ key: "debt", label: "Debt", color: QUIET },
|
|
91
|
+
{ key: "small", label: "Small cap", color: QUIET },
|
|
92
|
+
{ key: "intl", label: "International", color: QUIET },
|
|
93
|
+
{ key: "liquid", label: "Liquid", color: QUIET },
|
|
94
|
+
{ key: "midcap", label: "Mid cap", color: QUIET },
|
|
95
|
+
{ key: "nifty", label: "Nifty 50", color: "var(--chart-1)" },
|
|
96
|
+
{ key: "gold", label: "Gold", color: "var(--chart-2)" },
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
export default function ChartLineQuietExample() {
|
|
100
|
+
const { pct } = useFormat();
|
|
101
|
+
return (
|
|
102
|
+
<LineChartCard
|
|
103
|
+
title="Growth by fund"
|
|
104
|
+
description="Eight funds; the two you are watching in colour"
|
|
105
|
+
data={growth}
|
|
106
|
+
xKey="month"
|
|
107
|
+
series={series}
|
|
108
|
+
today="Oct"
|
|
109
|
+
forecastFrom="Oct"
|
|
110
|
+
valueFormatter={pct}
|
|
111
|
+
height={256}
|
|
112
|
+
/>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { LineChartCard, type ChartSeries } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// A sar sample every 10 minutes from 15:00; the numbers are made up for the catalogue.
|
|
4
|
+
const data = [
|
|
5
|
+
{ minute: 0, used: 4.1, anon: 2.9 },
|
|
6
|
+
{ minute: 10, used: 4.3, anon: 3.1 },
|
|
7
|
+
{ minute: 20, used: 4.6, anon: 3.4 },
|
|
8
|
+
{ minute: 30, used: 5.2, anon: 4.2 },
|
|
9
|
+
{ minute: 40, used: 7.8, anon: 7.1 },
|
|
10
|
+
{ minute: 50, used: 8.1, anon: 7.6 },
|
|
11
|
+
{ minute: 60, used: 6.2, anon: 5.3 },
|
|
12
|
+
{ minute: 70, used: 4.4, anon: 3.2 },
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
const series: ChartSeries<(typeof data)[number]> = [
|
|
16
|
+
{ key: "used", label: "Used", color: "var(--chart-1)" },
|
|
17
|
+
{ key: "anon", label: "Anon", color: "var(--chart-2)" },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const clock = (minute: number) => `${Math.floor(15 + minute / 60)}:${String(minute % 60).padStart(2, "0")}`;
|
|
21
|
+
|
|
22
|
+
export default function ChartLineTimelineExample() {
|
|
23
|
+
return (
|
|
24
|
+
<LineChartCard
|
|
25
|
+
title="Memory in use, GiB"
|
|
26
|
+
description="sar -r. Used excludes cache; anon is program memory."
|
|
27
|
+
data={data}
|
|
28
|
+
xKey="minute"
|
|
29
|
+
// Ticks on both ends of the domain: the first sits at the plot's left edge.
|
|
30
|
+
xDomain={[0, 70]}
|
|
31
|
+
xTicks={[0, 10, 20, 30, 40, 50, 60, 70]}
|
|
32
|
+
xFormatter={clock}
|
|
33
|
+
xTooltipFormatter={(minute) => `${clock(minute)} IST, 10-min average`}
|
|
34
|
+
series={series}
|
|
35
|
+
valueFormatter={(v) => v.toFixed(1)}
|
|
36
|
+
yTickFormatter={(v) => v.toFixed(0)}
|
|
37
|
+
curve="linear"
|
|
38
|
+
height={192}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { LineChartCard, ToggleGroup, ToggleGroupItem, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
3
|
+
|
|
4
|
+
const cumulative = [
|
|
5
|
+
{ month: "May", store: 0.012, category: 0.008 },
|
|
6
|
+
{ month: "Jun", store: 0.021, category: 0.015 },
|
|
7
|
+
{ month: "Jul", store: 0.034, category: 0.029 },
|
|
8
|
+
{ month: "Aug", store: -0.006, category: 0.004 },
|
|
9
|
+
{ month: "Sep", store: 0.041, category: 0.031 },
|
|
10
|
+
{ month: "Oct", store: 0.052, category: 0.036 },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const monthly = [
|
|
14
|
+
{ month: "May", store: 0.012, category: 0.008 },
|
|
15
|
+
{ month: "Jun", store: 0.009, category: 0.007 },
|
|
16
|
+
{ month: "Jul", store: 0.013, category: 0.014 },
|
|
17
|
+
{ month: "Aug", store: -0.039, category: -0.024 },
|
|
18
|
+
{ month: "Sep", store: 0.047, category: 0.027 },
|
|
19
|
+
{ month: "Oct", store: 0.011, category: 0.005 },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const series: ChartSeries<(typeof cumulative)[number]> = [
|
|
23
|
+
{ key: "store", label: "Our store", color: "var(--chart-1)" },
|
|
24
|
+
{ key: "category", label: "Category average", color: "var(--chart-2)" },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export default function ChartLineExample() {
|
|
28
|
+
const { pct } = useFormat();
|
|
29
|
+
const [mode, setMode] = useState("cumulative");
|
|
30
|
+
return (
|
|
31
|
+
<LineChartCard
|
|
32
|
+
title="Sales growth against the category"
|
|
33
|
+
description={mode === "cumulative" ? "Cumulative, from the start of May" : "Each month on its own"}
|
|
34
|
+
action={
|
|
35
|
+
<ToggleGroup
|
|
36
|
+
value={[mode]}
|
|
37
|
+
onValueChange={([next]) => {
|
|
38
|
+
// Pressing the selected mode again would leave none selected; keep it.
|
|
39
|
+
if (next) setMode(next);
|
|
40
|
+
}}
|
|
41
|
+
variant="outline"
|
|
42
|
+
size="sm"
|
|
43
|
+
aria-label="Mode"
|
|
44
|
+
>
|
|
45
|
+
<ToggleGroupItem value="cumulative">Cumulative growth</ToggleGroupItem>
|
|
46
|
+
<ToggleGroupItem value="monthly">Monthly growth</ToggleGroupItem>
|
|
47
|
+
</ToggleGroup>
|
|
48
|
+
}
|
|
49
|
+
data={mode === "cumulative" ? cumulative : monthly}
|
|
50
|
+
xKey="month"
|
|
51
|
+
series={series}
|
|
52
|
+
// A formatter goes in as it is: the card calls it with the value alone.
|
|
53
|
+
valueFormatter={pct}
|
|
54
|
+
height={256}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
}
|