@siyahi/ui 0.1.9-next.17 → 0.1.9-next.19

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.
Files changed (93) hide show
  1. package/README.md +77 -207
  2. package/agents/examples/accordion.tsx +39 -0
  3. package/agents/examples/alert.tsx +25 -0
  4. package/agents/examples/app-sidebar.tsx +38 -0
  5. package/agents/examples/avatar.tsx +14 -0
  6. package/agents/examples/badge.tsx +18 -0
  7. package/agents/examples/bar-list-labels.tsx +22 -0
  8. package/agents/examples/bar-list-sides.tsx +30 -0
  9. package/agents/examples/bar-list.tsx +24 -0
  10. package/agents/examples/breadcrumb.tsx +28 -0
  11. package/agents/examples/button.tsx +21 -0
  12. package/agents/examples/calendar.tsx +15 -0
  13. package/agents/examples/card.tsx +34 -0
  14. package/agents/examples/chart-area.tsx +38 -0
  15. package/agents/examples/chart-bar-flows.tsx +31 -0
  16. package/agents/examples/chart-bar-hourly.tsx +28 -0
  17. package/agents/examples/chart-bar-losses.tsx +29 -0
  18. package/agents/examples/chart-bar-sectors.tsx +70 -0
  19. package/agents/examples/chart-bar-years.tsx +40 -0
  20. package/agents/examples/chart-bar.tsx +56 -0
  21. package/agents/examples/chart-category-ticks.tsx +50 -0
  22. package/agents/examples/chart-line-events.tsx +47 -0
  23. package/agents/examples/chart-line-timeline.tsx +41 -0
  24. package/agents/examples/chart-line.tsx +57 -0
  25. package/agents/examples/code-block.tsx +38 -0
  26. package/agents/examples/collapsible.tsx +16 -0
  27. package/agents/examples/command.tsx +27 -0
  28. package/agents/examples/context-menu.tsx +15 -0
  29. package/agents/examples/copy-button.tsx +8 -0
  30. package/agents/examples/data-bar.tsx +121 -0
  31. package/agents/examples/data-table-filters.tsx +103 -0
  32. package/agents/examples/data-table.tsx +98 -0
  33. package/agents/examples/delta.tsx +13 -0
  34. package/agents/examples/dialog.tsx +28 -0
  35. package/agents/examples/distribution-bar-budget.tsx +30 -0
  36. package/agents/examples/distribution-bar-tug.tsx +72 -0
  37. package/agents/examples/dropdown-menu.tsx +31 -0
  38. package/agents/examples/formatters.tsx +42 -0
  39. package/agents/examples/heatmap-calendar.tsx +50 -0
  40. package/agents/examples/heatmap-status.tsx +51 -0
  41. package/agents/examples/heatmap-weekday.tsx +53 -0
  42. package/agents/examples/input.tsx +17 -0
  43. package/agents/examples/local-time.tsx +14 -0
  44. package/agents/examples/metric-strip.tsx +40 -0
  45. package/agents/examples/page-section.tsx +52 -0
  46. package/agents/examples/popover.tsx +23 -0
  47. package/agents/examples/price-chart.tsx +32 -0
  48. package/agents/examples/progress-tone.tsx +28 -0
  49. package/agents/examples/progress.tsx +10 -0
  50. package/agents/examples/scroll-area.tsx +20 -0
  51. package/agents/examples/section-cards-select.tsx +27 -0
  52. package/agents/examples/section-cards-trend.tsx +30 -0
  53. package/agents/examples/section-cards.tsx +48 -0
  54. package/agents/examples/select.tsx +27 -0
  55. package/agents/examples/separator.tsx +13 -0
  56. package/agents/examples/sheet.tsx +15 -0
  57. package/agents/examples/skeleton.tsx +11 -0
  58. package/agents/examples/slider.tsx +5 -0
  59. package/agents/examples/surfaces.tsx +115 -0
  60. package/agents/examples/table.tsx +50 -0
  61. package/agents/examples/tabs.tsx +16 -0
  62. package/agents/examples/toggle-group.tsx +12 -0
  63. package/agents/examples/toggle.tsx +11 -0
  64. package/agents/examples/tooltip.tsx +13 -0
  65. package/agents/examples/treemap.tsx +87 -0
  66. package/agents/manifest.json +931 -0
  67. package/agents/report-rules.json +7 -0
  68. package/dist/components/registry/charts/bar-chart-card.js +1 -0
  69. package/dist/components/registry/dashboardcn/bar-list.js +8 -7
  70. package/dist/components/registry/heatmap/calendar-heatmap.js +8 -1
  71. package/dist/components/registry/heatmap/status-heatmap.js +8 -1
  72. package/dist/components/registry/heatmap/weekday-heatmap.d.ts +6 -2
  73. package/dist/components/registry/heatmap/weekday-heatmap.js +56 -37
  74. package/dist/components/registry/niko-table/core/data-table-context.d.ts +2 -0
  75. package/dist/components/registry/niko-table/core/data-table-context.js +21 -0
  76. package/dist/components/registry/niko-table/core/data-table-grouped-row.js +3 -1
  77. package/dist/components/registry/niko-table/core/data-table-structure.js +15 -12
  78. package/dist/components/registry/niko-table/core/data-table.d.ts +2 -2
  79. package/dist/components/registry/niko-table/core/data-table.js +5 -1
  80. package/dist/components/registry/niko-table/filters/table-search-filter.js +1 -1
  81. package/dist/components/registry/niko-table/lib/flex-columns.d.ts +1 -1
  82. package/dist/components/registry/niko-table/lib/flex-columns.js +3 -3
  83. package/dist/components/registry/niko-table/lib/styles.d.ts +1 -1
  84. package/dist/components/registry/niko-table/lib/styles.js +2 -2
  85. package/dist/components/registry/sidebar-07/nav-main.js +7 -1
  86. package/dist/components/siyahi/treemap.js +46 -4
  87. package/dist/lib/chart-frame.js +180 -124
  88. package/dist/lib/chart-series.d.ts +1 -1
  89. package/dist/lib/format.js +32 -13
  90. package/dist/lib/heatmap-navigation.d.ts +8 -0
  91. package/dist/lib/heatmap-navigation.js +49 -0
  92. package/package.json +3 -1
  93. package/styles/siyahi.css +24 -0
@@ -0,0 +1,34 @@
1
+ import {
2
+ Button,
3
+ Card,
4
+ CardAction,
5
+ CardContent,
6
+ CardDescription,
7
+ CardFooter,
8
+ CardHeader,
9
+ CardTitle,
10
+ useFormat,
11
+ } from "@siyahi/ui";
12
+ import { DownloadIcon } from "lucide-react";
13
+
14
+ export default function CardExample() {
15
+ const { money } = useFormat();
16
+ return (
17
+ <Card>
18
+ <CardHeader>
19
+ <CardTitle>Portfolio value</CardTitle>
20
+ <CardDescription>Across all accounts</CardDescription>
21
+ <CardAction>
22
+ <Button variant="outline" size="sm">
23
+ <DownloadIcon />
24
+ CSV
25
+ </Button>
26
+ </CardAction>
27
+ </CardHeader>
28
+ <CardContent>
29
+ <p className="text-3xl font-semibold">{money(4512300)}</p>
30
+ </CardContent>
31
+ <CardFooter className="text-muted-foreground">Updated after the market close</CardFooter>
32
+ </Card>
33
+ );
34
+ }
@@ -0,0 +1,38 @@
1
+ import { AreaChartCard, ToggleGroup, ToggleGroupItem, useFormat, type ChartSeries } from "@siyahi/ui";
2
+
3
+ const data = [
4
+ { month: "May", value: 3820000, invested: 3600000 },
5
+ { month: "Jun", value: 3950000, invested: 3685000 },
6
+ { month: "Jul", value: 4110000, invested: 3770000 },
7
+ { month: "Aug", value: 4020000, invested: 3855000 },
8
+ { month: "Sep", value: 4380000, invested: 3940000 },
9
+ { month: "Oct", value: 4512300, invested: 4025000 },
10
+ ];
11
+
12
+ // Drawn in this order, so value sits over the money put in.
13
+ const series: ChartSeries<(typeof data)[number]> = [
14
+ { key: "invested", label: "Invested", color: "var(--chart-2)" },
15
+ { key: "value", label: "Value", color: "var(--chart-1)" },
16
+ ];
17
+
18
+ export default function ChartAreaExample() {
19
+ const { money, moneyCompact } = useFormat();
20
+ return (
21
+ <AreaChartCard
22
+ title="Portfolio value"
23
+ description="Month-end value against money put in"
24
+ action={
25
+ <ToggleGroup defaultValue={["6M"]} variant="outline" size="sm" aria-label="Range">
26
+ <ToggleGroupItem value="6M">6M</ToggleGroupItem>
27
+ <ToggleGroupItem value="1Y">1Y</ToggleGroupItem>
28
+ </ToggleGroup>
29
+ }
30
+ data={data}
31
+ xKey="month"
32
+ series={series}
33
+ valueFormatter={money}
34
+ yTickFormatter={moneyCompact}
35
+ height={256}
36
+ />
37
+ );
38
+ }
@@ -0,0 +1,31 @@
1
+ import { BarChartCard, useFormat, type ChartSeries } from "@siyahi/ui";
2
+
3
+ // Money into and out of the account each month; out is negative. Made-up figures.
4
+ const data = [
5
+ { month: "Jul", in: 84000, out: -52000 },
6
+ { month: "Aug", in: 61000, out: -73000 },
7
+ { month: "Sep", in: 92000, out: -48000 },
8
+ { month: "Oct", in: 70000, out: -66000 },
9
+ ];
10
+
11
+ const series: ChartSeries<(typeof data)[number]> = [
12
+ { key: "in", label: "In", color: "var(--positive)" },
13
+ { key: "out", label: "Out", color: "var(--negative)" },
14
+ ];
15
+
16
+ export default function ChartBarFlowsExample() {
17
+ const { money, moneyCompact } = useFormat();
18
+ return (
19
+ <BarChartCard
20
+ title="Cash in and out by month"
21
+ description="Money in above the line, money out below it"
22
+ data={data}
23
+ xKey="month"
24
+ series={series}
25
+ stacked
26
+ valueFormatter={money}
27
+ yTickFormatter={moneyCompact}
28
+ height={256}
29
+ />
30
+ );
31
+ }
@@ -0,0 +1,28 @@
1
+ import { BarChartCard } from "@siyahi/ui";
2
+
3
+ // Market 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
+ // F&O net realized 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: "F&O net realized", color: "var(--positive)", negativeColor: "var(--negative)" },
13
+ ];
14
+
15
+ export default function ChartBarLossesExample() {
16
+ const { money, moneyCompact } = useFormat();
17
+ return (
18
+ <BarChartCard
19
+ title="F&O realized 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,70 @@
1
+ import { useState } from "react";
2
+ import { BarChartCard, ToggleGroup, ToggleGroupItem, useFormat, type ChartSeries } from "@siyahi/ui";
3
+
4
+ // Share of equity by sector against an index's weights; made-up figures.
5
+ const WEIGHTS = {
6
+ "Nifty 50": [
7
+ { sector: "Financial Services", you: 0.34, index: 0.37 },
8
+ { sector: "Information Technology", you: 0.21, index: 0.13 },
9
+ { sector: "Oil, Gas & Consumable Fuels", you: 0.06, index: 0.1 },
10
+ { sector: "Fast Moving Consumer Goods", you: 0.12, index: 0.08 },
11
+ { sector: "Automobile and Auto Components", you: 0.09, index: 0.07 },
12
+ { sector: "Healthcare", you: 0.08, index: 0.04 },
13
+ ],
14
+ "Nifty 500": [
15
+ { sector: "Financial Services", you: 0.34, index: 0.31 },
16
+ { sector: "Information Technology", you: 0.21, index: 0.1 },
17
+ { sector: "Oil, Gas & Consumable Fuels", you: 0.06, index: 0.08 },
18
+ { sector: "Fast Moving Consumer Goods", you: 0.12, index: 0.07 },
19
+ { sector: "Automobile and Auto Components", you: 0.09, index: 0.07 },
20
+ { sector: "Healthcare", you: 0.08, index: 0.06 },
21
+ ],
22
+ };
23
+ type Index = keyof typeof WEIGHTS;
24
+ type Row = (typeof WEIGHTS)[Index][number];
25
+
26
+ export default function ChartBarSectorsExample() {
27
+ const { pct } = useFormat();
28
+ const [index, setIndex] = useState<Index>("Nifty 50");
29
+ const rows = WEIGHTS[index];
30
+ const series: ChartSeries<Row> = [
31
+ { key: "you", label: "You", color: "var(--chart-1)" },
32
+ { key: "index", label: index, color: "var(--chart-2)" },
33
+ ];
34
+ const gap = (row: Row) => {
35
+ const points = Math.abs(row.you - row.index) * 100;
36
+ return row.you >= row.index ? `▲${points.toFixed(1)} pts over` : `▼${points.toFixed(1)} pts under`;
37
+ };
38
+ return (
39
+ <BarChartCard
40
+ title="Sectors against the index"
41
+ description="Share of your equity and of the index, by sector"
42
+ action={
43
+ <ToggleGroup
44
+ value={[index]}
45
+ onValueChange={([next]) => {
46
+ // Pressing the selected index again would leave none selected; keep it.
47
+ if (next) setIndex(next as Index);
48
+ }}
49
+ variant="outline"
50
+ size="sm"
51
+ aria-label="Index"
52
+ >
53
+ <ToggleGroupItem value="Nifty 50">Nifty 50</ToggleGroupItem>
54
+ <ToggleGroupItem value="Nifty 500">Nifty 500</ToggleGroupItem>
55
+ </ToggleGroup>
56
+ }
57
+ horizontal
58
+ data={rows}
59
+ xKey="sector"
60
+ xTickDetail={(row) => `${pct(row.you)} vs ${pct(row.index)} · ${gap(row)}`}
61
+ series={series}
62
+ valueFormatter={(v) => pct(v)}
63
+ // Sideways, y is still the value: the axis runs 0 to 40% and the cap is a value level.
64
+ yDomain={[0, 0.4]}
65
+ referenceLines={[{ y: 0.3, label: "cap 30%", labelPosition: "insideBottomRight" }]}
66
+ height={rows.length * 56 + 48}
67
+ footer={<p className="text-muted-foreground">Company shares only; ETFs and funds are left out.</p>}
68
+ />
69
+ );
70
+ }
@@ -0,0 +1,40 @@
1
+ import { useState } from "react";
2
+ import { BarChartCard, useFormat, type ChartSeries } from "@siyahi/ui";
3
+
4
+ // Net realized gain 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 realized", 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 ? "▼" : "▲"}${moneyCompact(Math.abs(v))}`;
23
+ return (
24
+ <BarChartCard
25
+ title="Realized by financial year"
26
+ description={
27
+ year ? `${year} picked; click it again for every year` : "April to March, gross. 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", equity: 120000, debt: 40000, gold: 15000, cash: 9000, reits: 4000 },
6
+ { quarter: "Q2", equity: 95000, debt: 52000, gold: 20000, cash: 6000, reits: 3000 },
7
+ { quarter: "Q3", equity: 140000, debt: 38000, gold: 12000, cash: 11000, reits: 5000 },
8
+ { quarter: "Q4", equity: 160000, debt: 45000, gold: 25000, cash: 7000, reits: 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: "equity", label: "Equity", color: "var(--chart-1)" },
15
+ { key: "debt", label: "Debt", color: "var(--chart-2)" },
16
+ { key: "gold", label: "Gold", color: "var(--chart-3)" },
17
+ { key: "cash", label: "Cash", color: "var(--chart-4)" },
18
+ { key: "reits", label: "REITs", 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="Money invested by 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 sector"
34
+ description="Demo orders; one long category label on a narrow chart"
35
+ data={[
36
+ { sector: "Information Technology and Services", orders: 100 },
37
+ { sector: "Other", orders: 50 },
38
+ { sector: "Third", orders: 70 },
39
+ ]}
40
+ xKey="sector"
41
+ xTicks={["Information Technology and Services"]}
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,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", portfolio: 0.012, index: 0.008 },
6
+ { month: "Jun", portfolio: 0.021, index: 0.015 },
7
+ { month: "Jul", portfolio: 0.034, index: 0.029 },
8
+ { month: "Aug", portfolio: -0.006, index: 0.004 },
9
+ { month: "Sep", portfolio: 0.041, index: 0.031 },
10
+ { month: "Oct", portfolio: 0.052, index: 0.036 },
11
+ ];
12
+
13
+ const monthly = [
14
+ { month: "May", portfolio: 0.012, index: 0.008 },
15
+ { month: "Jun", portfolio: 0.009, index: 0.007 },
16
+ { month: "Jul", portfolio: 0.013, index: 0.014 },
17
+ { month: "Aug", portfolio: -0.039, index: -0.024 },
18
+ { month: "Sep", portfolio: 0.047, index: 0.027 },
19
+ { month: "Oct", portfolio: 0.011, index: 0.005 },
20
+ ];
21
+
22
+ const series: ChartSeries<(typeof cumulative)[number]> = [
23
+ { key: "portfolio", label: "Portfolio", color: "var(--chart-1)" },
24
+ { key: "index", label: "Nifty 50", 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="Return against the index"
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 return</ToggleGroupItem>
46
+ <ToggleGroupItem value="monthly">Monthly return</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
+ }
@@ -0,0 +1,38 @@
1
+ import {
2
+ CodeBlock,
3
+ CodeBlockActions,
4
+ CodeBlockContent,
5
+ CodeBlockCopyButton,
6
+ CodeBlockHeader,
7
+ CodeBlockTitle,
8
+ } from "@siyahi/ui";
9
+
10
+ const CHECK = "openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null";
11
+
12
+ const LOG = Array.from(
13
+ { length: 24 },
14
+ (_, i) =>
15
+ `19:${String(33 + Math.floor(i / 4)).padStart(2, "0")}:${String((i * 15) % 60).padStart(2, "0")} memory.pressure some avg10=${(12 + i * 3.1).toFixed(2)}`,
16
+ ).join("\n");
17
+
18
+ export default function CodeBlockExample() {
19
+ return (
20
+ <div className="flex flex-col gap-4">
21
+ <CodeBlock>
22
+ <CodeBlockHeader>
23
+ <CodeBlockTitle>Show the chain a server sends</CodeBlockTitle>
24
+ <CodeBlockActions>
25
+ <CodeBlockCopyButton value={CHECK} />
26
+ </CodeBlockActions>
27
+ </CodeBlockHeader>
28
+ <CodeBlockContent wrap>{CHECK}</CodeBlockContent>
29
+ </CodeBlock>
30
+ <CodeBlock size="sm">
31
+ <CodeBlockActions>
32
+ <CodeBlockCopyButton value={LOG} />
33
+ </CodeBlockActions>
34
+ <CodeBlockContent className="max-h-48">{LOG}</CodeBlockContent>
35
+ </CodeBlock>
36
+ </div>
37
+ );
38
+ }
@@ -0,0 +1,16 @@
1
+ import { Button, Collapsible, CollapsibleContent, CollapsibleTrigger } from "@siyahi/ui";
2
+ import { ChevronsUpDownIcon } from "lucide-react";
3
+
4
+ export default function CollapsibleExample() {
5
+ return (
6
+ <Collapsible className="flex max-w-sm flex-col gap-2">
7
+ <CollapsibleTrigger render={<Button variant="outline" className="w-fit" />}>
8
+ <ChevronsUpDownIcon />
9
+ How lots are matched
10
+ </CollapsibleTrigger>
11
+ <CollapsibleContent className="text-muted-foreground">
12
+ Sells are matched to the oldest buy first, as the tax rules require.
13
+ </CollapsibleContent>
14
+ </Collapsible>
15
+ );
16
+ }
@@ -0,0 +1,27 @@
1
+ import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@siyahi/ui";
2
+ import { ChartLineIcon, LandmarkIcon, WalletIcon } from "lucide-react";
3
+
4
+ export default function CommandExample() {
5
+ return (
6
+ <Command className="rounded-lg border">
7
+ <CommandInput placeholder="Jump to a page" />
8
+ <CommandList>
9
+ <CommandEmpty>No page matches.</CommandEmpty>
10
+ <CommandGroup heading="Pages">
11
+ <CommandItem>
12
+ <WalletIcon />
13
+ Holdings
14
+ </CommandItem>
15
+ <CommandItem>
16
+ <ChartLineIcon />
17
+ Realized
18
+ </CommandItem>
19
+ <CommandItem>
20
+ <LandmarkIcon />
21
+ Cash flow
22
+ </CommandItem>
23
+ </CommandGroup>
24
+ </CommandList>
25
+ </Command>
26
+ );
27
+ }
@@ -0,0 +1,15 @@
1
+ import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from "@siyahi/ui";
2
+
3
+ export default function ContextMenuExample() {
4
+ return (
5
+ <ContextMenu>
6
+ <ContextMenuTrigger className="flex h-24 w-full items-center justify-center rounded-lg border border-dashed text-muted-foreground">
7
+ Right-click or long-press here
8
+ </ContextMenuTrigger>
9
+ <ContextMenuContent>
10
+ <ContextMenuItem>Copy symbol</ContextMenuItem>
11
+ <ContextMenuItem>Open chart</ContextMenuItem>
12
+ </ContextMenuContent>
13
+ </ContextMenu>
14
+ );
15
+ }
@@ -0,0 +1,8 @@
1
+ import { CopyButton } from "@siyahi/ui";
2
+
3
+ // Every command on a setup page, for a reader who wants them all at once.
4
+ const ALL = ["brew install node@24", "corepack enable", "pnpm install"].join("\n");
5
+
6
+ export default function CopyButtonExample() {
7
+ return <CopyButton value={ALL} label="Copy all" />;
8
+ }