@siyahi/ui 0.1.9-next.21 → 0.1.9-next.23

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/DESIGN.md +16 -3
  2. package/agents/examples/accordion.tsx +7 -7
  3. package/agents/examples/alert.tsx +16 -15
  4. package/agents/examples/app-sidebar.tsx +3 -1
  5. package/agents/examples/badge.tsx +20 -12
  6. package/agents/examples/bar-list-labels.tsx +6 -6
  7. package/agents/examples/bar-list-sides.tsx +18 -16
  8. package/agents/examples/bar-list.tsx +8 -8
  9. package/agents/examples/breadcrumb.tsx +3 -3
  10. package/agents/examples/calendar.tsx +3 -7
  11. package/agents/examples/callout.tsx +15 -15
  12. package/agents/examples/card.tsx +5 -3
  13. package/agents/examples/change-bar.tsx +21 -21
  14. package/agents/examples/chart-area.tsx +11 -11
  15. package/agents/examples/chart-bar-flows.tsx +1 -1
  16. package/agents/examples/chart-bar-hourly.tsx +1 -1
  17. package/agents/examples/chart-bar-losses.tsx +3 -3
  18. package/agents/examples/chart-bar-teams.tsx +72 -0
  19. package/agents/examples/chart-bar-years.tsx +5 -5
  20. package/agents/examples/chart-bar.tsx +10 -10
  21. package/agents/examples/chart-category-ticks.tsx +6 -6
  22. package/agents/examples/chart-line.tsx +17 -17
  23. package/agents/examples/collapsible.tsx +5 -3
  24. package/agents/examples/command.tsx +23 -21
  25. package/agents/examples/context-menu.tsx +6 -4
  26. package/agents/examples/data-bar.tsx +32 -45
  27. package/agents/examples/data-table-compact.tsx +31 -30
  28. package/agents/examples/data-table-filters.tsx +20 -20
  29. package/agents/examples/data-table.tsx +31 -30
  30. package/agents/examples/dialog.tsx +3 -3
  31. package/agents/examples/distribution-bar-tug.tsx +36 -34
  32. package/agents/examples/dropdown-menu.tsx +2 -2
  33. package/agents/examples/heatmap-calendar.tsx +12 -10
  34. package/agents/examples/heatmap-status.tsx +11 -9
  35. package/agents/examples/heatmap-weekday.tsx +27 -30
  36. package/agents/examples/input-states.tsx +9 -9
  37. package/agents/examples/input.tsx +3 -3
  38. package/agents/examples/local-time.tsx +1 -1
  39. package/agents/examples/metric-strip.tsx +8 -8
  40. package/agents/examples/page-hero.tsx +2 -2
  41. package/agents/examples/popover.tsx +3 -3
  42. package/agents/examples/price-chart.tsx +5 -5
  43. package/agents/examples/progress-tone.tsx +10 -9
  44. package/agents/examples/progress.tsx +1 -1
  45. package/agents/examples/range-position-table.tsx +31 -31
  46. package/agents/examples/range-position.tsx +31 -29
  47. package/agents/examples/scroll-area.tsx +12 -10
  48. package/agents/examples/section-cards-select.tsx +11 -10
  49. package/agents/examples/section-cards-trend.tsx +4 -4
  50. package/agents/examples/section-cards.tsx +13 -13
  51. package/agents/examples/select.tsx +9 -9
  52. package/agents/examples/separator.tsx +3 -3
  53. package/agents/examples/sheet.tsx +1 -1
  54. package/agents/examples/slider.tsx +1 -1
  55. package/agents/examples/surfaces.tsx +16 -16
  56. package/agents/examples/tabs.tsx +7 -7
  57. package/agents/examples/target-rows.tsx +31 -27
  58. package/agents/examples/tooltip.tsx +2 -2
  59. package/agents/examples/treemap.tsx +38 -33
  60. package/agents/manifest.json +15 -15
  61. package/dist/components/registry/charts/bar-chart-card.d.ts +1 -1
  62. package/dist/components/registry/charts/bar-chart-card.js +6 -2
  63. package/dist/components/registry/charts/line-chart-card.d.ts +1 -1
  64. package/dist/components/registry/charts/line-chart-card.js +1 -1
  65. package/dist/components/registry/dashboard-01/section-cards.js +1 -1
  66. package/dist/components/registry/dashboardcn/distribution-bar.js +5 -3
  67. package/dist/components/registry/heatmap/status-heatmap.js +1 -1
  68. package/dist/components/siyahi/callout.d.ts +5 -12
  69. package/dist/components/siyahi/callout.js +5 -11
  70. package/dist/components/siyahi/delta.d.ts +5 -1
  71. package/dist/components/siyahi/delta.js +14 -9
  72. package/dist/components/siyahi/status-alert.d.ts +15 -0
  73. package/dist/components/siyahi/status-alert.js +29 -0
  74. package/dist/components/siyahi/status-badge.d.ts +15 -0
  75. package/dist/components/siyahi/status-badge.js +24 -0
  76. package/dist/components/siyahi/tone-progress.d.ts +1 -1
  77. package/dist/components/siyahi/tone-progress.js +1 -1
  78. package/dist/components/siyahi/treemap.d.ts +4 -4
  79. package/dist/components/siyahi/treemap.js +5 -5
  80. package/dist/index.d.ts +5 -4
  81. package/dist/index.js +3 -2
  82. package/dist/lib/chart-frame.js +1 -1
  83. package/dist/lib/chart-series.d.ts +1 -1
  84. package/dist/lib/format.d.ts +1 -1
  85. package/dist/lib/format.js +1 -1
  86. package/dist/lib/tone.d.ts +36 -0
  87. package/dist/lib/tone.js +35 -0
  88. package/package.json +1 -1
  89. package/report.css +14 -14
  90. package/styles/siyahi.css +92 -20
  91. package/agents/examples/chart-bar-sectors.tsx +0 -72
  92. package/dist/components/siyahi/warning-alert.d.ts +0 -10
  93. package/dist/components/siyahi/warning-alert.js +0 -20
@@ -18,21 +18,22 @@ import {
18
18
  type DataTableColumnDef,
19
19
  } from "@siyahi/ui";
20
20
 
21
- interface Holding {
22
- symbol: string;
23
- sector: string;
24
- quantity: number;
25
- value: number;
21
+ interface Product {
22
+ product: string;
23
+ category: string;
24
+ /** Units sold and revenue this month; change is the revenue against last week. Made-up figures. */
25
+ units: number;
26
+ revenue: number;
26
27
  change: number;
27
28
  }
28
29
 
29
- const holdings: Holding[] = [
30
- { symbol: "INFY", sector: "IT", quantity: 120, value: 224400, change: 0.018 },
31
- { symbol: "HDFCBANK", sector: "Banks", quantity: 150, value: 262500, change: -0.006 },
32
- { symbol: "TCS", sector: "IT", quantity: 40, value: 166000, change: 0.004 },
33
- { symbol: "ITC", sector: "Fast Moving Consumer Goods", quantity: 600, value: 276000, change: -0.012 },
34
- { symbol: "ICICIBANK", sector: "Banks", quantity: 200, value: 258000, change: 0.022 },
35
- { symbol: "NIFTYBEES", sector: "ETF", quantity: 900, value: 255600, change: 0.009 },
30
+ const products: Product[] = [
31
+ { product: "Standing desk", category: "Furniture", units: 120, revenue: 224400, change: 0.018 },
32
+ { product: "Office chair", category: "Seating", units: 150, revenue: 262500, change: -0.006 },
33
+ { product: "Bookshelf", category: "Furniture", units: 40, revenue: 166000, change: 0.004 },
34
+ { product: "Dinner set", category: "Kitchen, Dining & Tableware", units: 600, revenue: 276000, change: -0.012 },
35
+ { product: "Kids chair", category: "Seating", units: 200, revenue: 258000, change: 0.022 },
36
+ { product: "Desk lamp", category: "Lighting", units: 900, revenue: 255600, change: 0.009 },
36
37
  ];
37
38
 
38
39
  // One click sorts largest (or Z) first; the title comes from meta.label.
@@ -42,22 +43,22 @@ function Money({ amount }: { amount: number }) {
42
43
  return useFormat().money(amount);
43
44
  }
44
45
 
45
- const columns: DataTableColumnDef<Holding>[] = [
46
- { accessorKey: "symbol", header, size: 140, meta: { label: "Symbol" } },
47
- { accessorKey: "sector", header, size: 120, meta: { label: "Sector" } },
48
- { accessorKey: "quantity", header, size: 100, meta: { label: "Qty", variant: "number" } },
46
+ const columns: DataTableColumnDef<Product>[] = [
47
+ { accessorKey: "product", header, size: 140, meta: { label: "Product" } },
48
+ { accessorKey: "category", header, size: 120, meta: { label: "Category" } },
49
+ { accessorKey: "units", header, size: 100, meta: { label: "Units", variant: "number" } },
49
50
  {
50
- accessorKey: "value",
51
+ accessorKey: "revenue",
51
52
  header,
52
53
  size: 140,
53
- meta: { label: "Value", variant: "number" },
54
- cell: ({ row }) => <Money amount={row.original.value} />,
54
+ meta: { label: "Revenue", variant: "number" },
55
+ cell: ({ row }) => <Money amount={row.original.revenue} />,
55
56
  },
56
57
  {
57
58
  accessorKey: "change",
58
59
  header,
59
60
  size: 110,
60
- meta: { label: "Day", variant: "number" },
61
+ meta: { label: "Week", variant: "number" },
61
62
  cell: ({ row }) => <Delta value={row.original.change} />,
62
63
  },
63
64
  ];
@@ -66,28 +67,28 @@ export default function DataTableExample() {
66
67
  return (
67
68
  <Card>
68
69
  <CardHeader>
69
- <CardTitle>Holdings</CardTitle>
70
+ <CardTitle>Products</CardTitle>
70
71
  <CardDescription>
71
- Search every column, filter by sector, sort any column in one click; the symbol stays put when the table
72
- scrolls in wide panels. In narrow panels every column scrolls, leaving room for the values
72
+ Search every column, filter by category, sort any column in one click; the product stays put when the table
73
+ scrolls in wide panels. In narrow panels every column scrolls, leaving room for the figures
73
74
  </CardDescription>
74
75
  </CardHeader>
75
76
  <CardContent>
76
77
  <DataTableRoot
77
- data={holdings}
78
+ data={products}
78
79
  columns={columns}
79
- initialState={{ columnPinning: { start: ["symbol"], end: [] } }}
80
+ initialState={{ columnPinning: { start: ["product"], end: [] } }}
80
81
  >
81
82
  <DataTableToolbarSection>
82
83
  <DataTableSearchFilter
83
- placeholder="Search holdings…"
84
- label="Filter holdings"
84
+ placeholder="Search products…"
85
+ label="Filter products"
85
86
  className="flex-none sm:w-64"
86
87
  />
87
- <DataTableFacetedFilter accessorKey="sector" title="Sector" />
88
- <DataTableRowCount unit="holdings" />
88
+ <DataTableFacetedFilter accessorKey="category" title="Category" />
89
+ <DataTableRowCount unit="products" />
89
90
  </DataTableToolbarSection>
90
- <DataTable aria-label="Holdings">
91
+ <DataTable aria-label="Products">
91
92
  <DataTableHeader />
92
93
  <DataTableBody />
93
94
  </DataTable>
@@ -13,11 +13,11 @@ import {
13
13
  export default function DialogExample() {
14
14
  return (
15
15
  <Dialog>
16
- <DialogTrigger render={<Button variant="outline" className="w-fit" />}>Show fills</DialogTrigger>
16
+ <DialogTrigger render={<Button variant="outline" className="w-fit" />}>Show parcels</DialogTrigger>
17
17
  <DialogContent>
18
18
  <DialogHeader>
19
- <DialogTitle>Fills for this sell</DialogTitle>
20
- <DialogDescription>Each lot this sale was matched against, oldest first.</DialogDescription>
19
+ <DialogTitle>Parcels for this order</DialogTitle>
20
+ <DialogDescription>Each parcel this order was split into, earliest first.</DialogDescription>
21
21
  </DialogHeader>
22
22
  <DialogFooter>
23
23
  <DialogClose render={<Button variant="outline" />}>Close</DialogClose>
@@ -11,17 +11,17 @@ import {
11
11
  type DistributionSegment,
12
12
  } from "@siyahi/ui";
13
13
 
14
- // Each closed position's net realized, ₹; made-up figures.
15
- const positions = [
16
- { name: "INFY", value: 61000 },
17
- { name: "TCS", value: 38000 },
18
- { name: "HDFCBANK", value: 17000 },
19
- { name: "ITC", value: -26000 },
20
- { name: "WIPRO", value: -14000 },
21
- { name: "SBIN", value: -6000 },
14
+ // Each finished marketing campaign's net return, ₹: sales it brought in less what it cost; made-up figures.
15
+ const campaigns = [
16
+ { name: "Festive sale", value: 61000 },
17
+ { name: "Referrals", value: 38000 },
18
+ { name: "Email win-back", value: 17000 },
19
+ { name: "Billboards", value: -26000 },
20
+ { name: "Podcast ads", value: -14000 },
21
+ { name: "Trade fair", value: -6000 },
22
22
  ];
23
- const won = positions.filter((p) => p.value > 0).reduce((sum, p) => sum + p.value, 0);
24
- const lost = positions.filter((p) => p.value < 0).reduce((sum, p) => sum + p.value, 0);
23
+ const won = campaigns.filter((c) => c.value > 0).reduce((sum, c) => sum + c.value, 0);
24
+ const lost = campaigns.filter((c) => c.value < 0).reduce((sum, c) => sum + c.value, 0);
25
25
  // One scale both ways, so whichever side reaches farther is the net.
26
26
  const reach = Math.max(won, -lost);
27
27
 
@@ -31,30 +31,32 @@ export default function DistributionBarTugExample() {
31
31
  <Card>
32
32
  <CardHeader>
33
33
  <CardTitle>The tug-of-war</CardTitle>
34
- <CardDescription>Each closed position, losses left of break-even and gains right</CardDescription>
34
+ <CardDescription>Each finished campaign, losses left of break-even and gains right</CardDescription>
35
35
  </CardHeader>
36
- <CardContent className="flex flex-col gap-2">
37
- <DistributionBar
38
- min={-reach}
39
- max={reach}
40
- showLegend={false}
41
- markers={[{ at: 0 }]}
42
- highlighted={focus?.name ?? null}
43
- onHover={setFocus}
44
- segments={positions.map(({ name, value }) => ({
45
- name,
46
- value,
47
- color: value > 0 ? "var(--positive)" : "var(--negative)",
48
- }))}
49
- />
50
- <div className="grid grid-cols-3 text-xs text-muted-foreground tabular-nums">
51
- <span>
52
- losers <Delta value={lost} format="money" />
53
- </span>
54
- <span className="text-center">break-even</span>
55
- <span className="text-right">
56
- winners <Delta value={won} format="money" />
57
- </span>
36
+ <CardContent>
37
+ <div className="flex flex-col gap-2">
38
+ <DistributionBar
39
+ min={-reach}
40
+ max={reach}
41
+ showLegend={false}
42
+ markers={[{ at: 0 }]}
43
+ highlighted={focus?.name ?? null}
44
+ onHover={setFocus}
45
+ segments={campaigns.map(({ name, value }) => ({
46
+ name,
47
+ value,
48
+ color: value > 0 ? "var(--positive)" : "var(--negative)",
49
+ }))}
50
+ />
51
+ <div className="grid grid-cols-3 text-xs text-muted-foreground tabular-nums">
52
+ <span>
53
+ lost <Delta value={lost} format="money" />
54
+ </span>
55
+ <span className="text-center">break-even</span>
56
+ <span className="text-right">
57
+ earned <Delta value={won} format="money" />
58
+ </span>
59
+ </div>
58
60
  </div>
59
61
  </CardContent>
60
62
  <CardFooter className="min-h-12" aria-live="polite">
@@ -64,7 +66,7 @@ export default function DistributionBarTugExample() {
64
66
  <Delta value={focus.value} format="money" />
65
67
  </p>
66
68
  ) : (
67
- <p className="text-muted-foreground">Hover a band to see its position.</p>
69
+ <p className="text-muted-foreground">Hover a band to see its campaign.</p>
68
70
  )}
69
71
  </CardFooter>
70
72
  </Card>
@@ -19,8 +19,8 @@ export default function DropdownMenuExample() {
19
19
  </DropdownMenuTrigger>
20
20
  <DropdownMenuContent>
21
21
  <DropdownMenuGroup>
22
- <DropdownMenuLabel>Holding</DropdownMenuLabel>
23
- <DropdownMenuItem>View lots</DropdownMenuItem>
22
+ <DropdownMenuLabel>Order</DropdownMenuLabel>
23
+ <DropdownMenuItem>View parcels</DropdownMenuItem>
24
24
  <DropdownMenuItem>Export CSV</DropdownMenuItem>
25
25
  </DropdownMenuGroup>
26
26
  <DropdownMenuSeparator />
@@ -13,7 +13,7 @@ import {
13
13
  CardTitle,
14
14
  } from "@siyahi/ui";
15
15
 
16
- // A year of trading days with a count of trades on each.
16
+ // A year of working days with a count of production deploys on each.
17
17
  const data = Array.from({ length: 365 }, (_, i) => {
18
18
  const day = new Date(Date.UTC(2025, 9, 20 + i));
19
19
  const weekday = day.getUTCDay();
@@ -29,11 +29,11 @@ export default function HeatmapCalendarExample() {
29
29
  return (
30
30
  <Card>
31
31
  <CardHeader>
32
- <CardTitle>Trades per day</CardTitle>
32
+ <CardTitle>Deploys per day</CardTitle>
33
33
  <CardDescription>The last 12 months; counts use a single-hue fade of --chart-1</CardDescription>
34
34
  </CardHeader>
35
35
  <CardContent>
36
- <CalendarHeatmap data={data} labels={{ heatmapLabel: "Trades per day over the last 12 months" }}>
36
+ <CalendarHeatmap data={data} labels={{ heatmapLabel: "Deploys per day over the last 12 months" }}>
37
37
  <CalendarHeatmapBody>
38
38
  {({ activity, dayIndex, weekIndex }) => (
39
39
  <CalendarHeatmapBlock
@@ -45,13 +45,15 @@ export default function HeatmapCalendarExample() {
45
45
  />
46
46
  )}
47
47
  </CalendarHeatmapBody>
48
- <CalendarHeatmapFooter className="items-center justify-between gap-x-6 gap-y-2 whitespace-normal">
49
- <p aria-live="polite" className="text-sm">
50
- {picked
51
- ? `${picked.date}: ${count(picked.value)} trades`
52
- : "Select a day for its trade count. Use arrow keys to move between days."}
53
- </p>
54
- <CalendarHeatmapLegend labels={{ less: "0 trades", more: `${count(busiest)} trades` }} />
48
+ <CalendarHeatmapFooter className="whitespace-normal">
49
+ <div className="flex w-full flex-wrap items-center justify-between gap-x-6 gap-y-2">
50
+ <p aria-live="polite" className="text-sm">
51
+ {picked
52
+ ? `${picked.date}: ${count(picked.value)} deploys`
53
+ : "Select a day for its deploy count. Use arrow keys to move between days."}
54
+ </p>
55
+ <CalendarHeatmapLegend labels={{ less: "0 deploys", more: `${count(busiest)} deploys` }} />
56
+ </div>
55
57
  </CalendarHeatmapFooter>
56
58
  </CalendarHeatmap>
57
59
  </CardContent>
@@ -26,7 +26,7 @@ export default function HeatmapStatusExample() {
26
26
  return (
27
27
  <Card>
28
28
  <CardHeader>
29
- <CardTitle>Price feed</CardTitle>
29
+ <CardTitle>Checkout API</CardTitle>
30
30
  <CardDescription>Daily health: healthy, degraded or critical</CardDescription>
31
31
  </CardHeader>
32
32
  <CardContent>
@@ -41,14 +41,16 @@ export default function HeatmapStatusExample() {
41
41
  />
42
42
  )}
43
43
  </StatusHeatmapBody>
44
- <StatusHeatmapFooter className="items-center justify-between gap-x-6 gap-y-2 whitespace-normal">
45
- <p aria-live="polite" className="text-sm">
46
- {picked
47
- ? `${picked.date}: ${["unknown", "critical", "degraded", "healthy"][picked.value] ?? "unknown"}`
48
- : "Select a day for its health. Use arrow keys to move between days."}
49
- </p>
50
- {/* No day lacks data, so the legend leaves out "No Data". */}
51
- <StatusHeatmapLegend className="gap-3" />
44
+ <StatusHeatmapFooter className="whitespace-normal">
45
+ <div className="flex w-full flex-wrap items-center justify-between gap-x-6 gap-y-2">
46
+ <p aria-live="polite" className="text-sm">
47
+ {picked
48
+ ? `${picked.date}: ${["unknown", "critical", "degraded", "healthy"][picked.value] ?? "unknown"}`
49
+ : "Select a day for its health. Use arrow keys to move between days."}
50
+ </p>
51
+ {/* No day lacks data, so the legend leaves out "No Data". */}
52
+ <StatusHeatmapLegend />
53
+ </div>
52
54
  </StatusHeatmapFooter>
53
55
  </StatusHeatmap>
54
56
  </CardContent>
@@ -12,7 +12,7 @@ import {
12
12
  WeekdayHeatmapLegend,
13
13
  } from "@siyahi/ui";
14
14
 
15
- // Orders placed by weekday and hour of the trading session.
15
+ // Support tickets opened by weekday and office hour; the overnight queue lands at 9.
16
16
  const data = [1, 2, 3, 4, 5].flatMap((weekday) =>
17
17
  [9, 10, 11, 12, 13, 14, 15].map((hour) => ({
18
18
  weekday,
@@ -33,40 +33,37 @@ export default function HeatmapWeekdayExample() {
33
33
  return (
34
34
  <Card>
35
35
  <CardHeader>
36
- <CardTitle>When orders are placed</CardTitle>
37
- <CardDescription>Weekday by hour in India Standard Time, market hours only</CardDescription>
36
+ <CardTitle>When support tickets arrive</CardTitle>
37
+ <CardDescription>Weekday by hour in India Standard Time, office hours only</CardDescription>
38
38
  </CardHeader>
39
39
  {/* Seven hours by five days is a small grid: capped, it keeps square cells, and the legend and the answer
40
40
  sit beside it instead of a wide empty card. */}
41
41
  <CardContent>
42
- <WeekdayHeatmap
43
- data={data}
44
- hours={[9, 10, 11, 12, 13, 14, 15]}
45
- weekdays={[1, 2, 3, 4, 5]}
46
- className="gap-4 lg:flex-row lg:items-center lg:gap-8"
47
- >
48
- <WeekdayHeatmapBody className="lg:w-md lg:shrink-0">
49
- {({ activity }) => (
50
- <WeekdayHeatmapBlock
51
- activity={activity}
52
- selected={isPicked(activity)}
53
- onCellClick={(cell) => setPicked(isPicked(cell) ? null : cell)}
42
+ <WeekdayHeatmap data={data} hours={[9, 10, 11, 12, 13, 14, 15]} weekdays={[1, 2, 3, 4, 5]}>
43
+ <div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:gap-8">
44
+ <WeekdayHeatmapBody className="lg:w-md lg:shrink-0">
45
+ {({ activity }) => (
46
+ <WeekdayHeatmapBlock
47
+ activity={activity}
48
+ selected={isPicked(activity)}
49
+ onCellClick={(cell) => setPicked(isPicked(cell) ? null : cell)}
50
+ />
51
+ )}
52
+ </WeekdayHeatmapBody>
53
+ <div className="flex flex-col items-start gap-3 text-sm">
54
+ <WeekdayHeatmapLegend
55
+ className="ml-0"
56
+ labels={{ less: "0 tickets", more: `${count(busiest.value)} tickets an hour` }}
54
57
  />
55
- )}
56
- </WeekdayHeatmapBody>
57
- <div className="flex flex-col items-start gap-3 text-sm">
58
- <WeekdayHeatmapLegend
59
- className="ml-0"
60
- labels={{ less: "0 orders", more: `${count(busiest.value)} orders an hour` }}
61
- />
62
- <p>
63
- Busiest: {DAYS[busiest.weekday]} at {hourLabel(busiest.hour)}, {count(busiest.value)} orders
64
- </p>
65
- <p aria-live="polite" className="text-muted-foreground">
66
- {picked
67
- ? `${DAYS[picked.weekday]}, ${hourLabel(picked.hour)} IST: ${count(picked.value)} orders`
68
- : "Select a cell for its order count. Use arrow keys to move between cells."}
69
- </p>
58
+ <p>
59
+ Busiest: {DAYS[busiest.weekday]} at {hourLabel(busiest.hour)}, {count(busiest.value)} tickets
60
+ </p>
61
+ <p aria-live="polite" className="text-muted-foreground">
62
+ {picked
63
+ ? `${DAYS[picked.weekday]}, ${hourLabel(picked.hour)} IST: ${count(picked.value)} tickets`
64
+ : "Select a cell for its ticket count. Use arrow keys to move between cells."}
65
+ </p>
66
+ </div>
70
67
  </div>
71
68
  </WeekdayHeatmap>
72
69
  </CardContent>
@@ -10,23 +10,23 @@ export default function InputStatesExample() {
10
10
  </label>
11
11
  <Input id="budget" inputMode="numeric" defaultValue="25,000" aria-describedby="budget-hint" />
12
12
  <p id="budget-hint" className="text-sm text-muted-foreground">
13
- In rupees, before brokerage
13
+ In rupees, before tax
14
14
  </p>
15
15
  </div>
16
16
  <div className="grid gap-1.5">
17
- <label htmlFor="folio" className="text-sm font-medium">
18
- Folio number
17
+ <label htmlFor="pin" className="text-sm font-medium">
18
+ PIN code
19
19
  </label>
20
- <Input id="folio" defaultValue="12/34" aria-invalid aria-describedby="folio-error" />
21
- <p id="folio-error" className="text-sm text-destructive">
22
- A folio is digits only, such as 1234567
20
+ <Input id="pin" defaultValue="56/001" aria-invalid aria-describedby="pin-error" />
21
+ <p id="pin-error" className="text-sm text-destructive">
22
+ A PIN code is six digits, such as 560001
23
23
  </p>
24
24
  </div>
25
25
  <div className="grid gap-1.5">
26
- <label htmlFor="broker" className="text-sm font-medium text-muted-foreground">
27
- Broker
26
+ <label htmlFor="team" className="text-sm font-medium text-muted-foreground">
27
+ Team
28
28
  </label>
29
- <Input id="broker" defaultValue="Kite" disabled />
29
+ <Input id="team" defaultValue="Finance" disabled />
30
30
  </div>
31
31
  </div>
32
32
  );
@@ -4,14 +4,14 @@ import { SearchIcon } from "lucide-react";
4
4
  export default function InputExample() {
5
5
  return (
6
6
  <div className="flex max-w-sm flex-col gap-3">
7
- <Input placeholder="Folio number" aria-label="Folio number" />
7
+ <Input placeholder="Order number" aria-label="Order number" />
8
8
  <InputGroup>
9
9
  <InputGroupAddon>
10
10
  <SearchIcon />
11
11
  </InputGroupAddon>
12
- <InputGroupInput placeholder="Search symbols" aria-label="Search symbols" />
12
+ <InputGroupInput placeholder="Search customers" aria-label="Search customers" />
13
13
  </InputGroup>
14
- <Textarea placeholder="Note for this trade" aria-label="Note" />
14
+ <Textarea placeholder="Note for this order" aria-label="Note" />
15
15
  </div>
16
16
  );
17
17
  }
@@ -4,7 +4,7 @@ export default function LocalTimeExample() {
4
4
  return (
5
5
  <>
6
6
  <p>
7
- Prices as of <LocalTime value="2026-10-20T10:00:00Z" />. Hover the time to see it on your own clock.
7
+ Figures as of <LocalTime value="2026-10-20T10:00:00Z" />. Hover the time to see it on your own clock.
8
8
  </p>
9
9
  <p>
10
10
  Daily snapshot of <LocalTime value="2026-06-26T04:11:00Z" withDate />.
@@ -5,33 +5,33 @@ export default function MetricStripExample() {
5
5
  // trend is each figure's month-end run, oldest first.
6
6
  const items: MetricStripItem[] = [
7
7
  {
8
- label: "Portfolio value",
8
+ label: "Revenue",
9
9
  value: money(4512300),
10
10
  change: 0.031,
11
11
  note: "vs Sep",
12
12
  trend: [3820000, 3950000, 4110000, 4020000, 4380000, 4512300],
13
13
  },
14
14
  {
15
- label: "Invested",
15
+ label: "Target",
16
16
  value: moneyCompact(4025000),
17
17
  change: 85000,
18
18
  changeFormat: "money",
19
19
  trend: [3600000, 3685000, 3770000, 3855000, 3940000, 4025000],
20
20
  },
21
- { label: "XIRR", value: pct(0.142), change: -0.004, trend: [0.151, 0.149, 0.152, 0.144, 0.146, 0.142] },
21
+ { label: "Gross margin", value: pct(0.142), change: -0.004, trend: [0.151, 0.149, 0.152, 0.144, 0.146, 0.142] },
22
22
  {
23
- label: "Realised",
23
+ label: "Cash flow",
24
24
  value: moneyCompact(-61200),
25
25
  change: -61200,
26
26
  changeFormat: "money",
27
27
  trend: [14200, -3800, 9100, 2600, -18400, -61200],
28
28
  },
29
- { label: "Dividends", value: moneyCompact(38400), change: 0.18, trend: [4100, 0, 12800, 3300, 9900, 8300] },
30
- { label: "Holdings", value: count(42), note: "3 bought in Oct", trend: [38, 39, 39, 40, 39, 42] },
29
+ { label: "Gift cards", value: moneyCompact(38400), change: 0.18, trend: [4100, 0, 12800, 3300, 9900, 8300] },
30
+ { label: "Products", value: count(42), note: "3 added in Oct", trend: [38, 39, 39, 40, 39, 42] },
31
31
  ];
32
32
  return (
33
33
  <MetricStrip
34
- title="Portfolio up 3.1% in October"
34
+ title="Revenue up 3.1% in October"
35
35
  description="Month-end figures with the six-month run behind each"
36
36
  action={
37
37
  <ToggleGroup defaultValue={["1M"]} variant="outline" size="sm" aria-label="Period">
@@ -40,7 +40,7 @@ export default function MetricStripExample() {
40
40
  </ToggleGroup>
41
41
  }
42
42
  items={items}
43
- footer={<p className="text-muted-foreground">Valued at the last close, 31 Oct 2026</p>}
43
+ footer={<p className="text-muted-foreground">Booked up to 31 Oct 2026</p>}
44
44
  />
45
45
  );
46
46
  }
@@ -19,8 +19,8 @@ export default function PageHeroExample() {
19
19
  <PageHero
20
20
  eyebrow="@siyahi/ui"
21
21
  title="Siyahi"
22
- lead="Ink for numbers. A design system for pages people read figures from: portfolios, ledgers, research."
23
- detail="Stock shadcn/ui on Base UI and Tailwind v4, with a finance theme, charts and tables that fit a phone, Indian-aware formatters and a lint. Siyahi is Hindi for ink."
22
+ lead="Ink for numbers. A design system for pages people read figures from: dashboards, ledgers, reports."
23
+ detail="Stock shadcn/ui on Base UI and Tailwind v4, with a theme for figures, charts and tables that fit a phone, Indian-aware formatters and a lint. Siyahi is Hindi for ink."
24
24
  actions={
25
25
  <>
26
26
  <Button nativeButton={false} render={<a href="#/data" />}>
@@ -11,11 +11,11 @@ import {
11
11
  export default function PopoverExample() {
12
12
  return (
13
13
  <Popover>
14
- <PopoverTrigger render={<Button variant="outline" className="w-fit" />}>How is this priced?</PopoverTrigger>
14
+ <PopoverTrigger render={<Button variant="outline" className="w-fit" />}>How is this counted?</PopoverTrigger>
15
15
  <PopoverContent align="start">
16
16
  <PopoverHeader>
17
- <PopoverTitle>Last close</PopoverTitle>
18
- <PopoverDescription>Holdings are valued at the exchange's last closing price.</PopoverDescription>
17
+ <PopoverTitle>Paid orders</PopoverTitle>
18
+ <PopoverDescription>Revenue counts paid orders, less refunds, on the day each was placed.</PopoverDescription>
19
19
  </PopoverHeader>
20
20
  </PopoverContent>
21
21
  </Popover>
@@ -1,6 +1,6 @@
1
1
  import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, PriceChart } from "@siyahi/ui";
2
2
 
3
- // A made-up daily close series for one year.
3
+ // A made-up daily series for one year: the average order value, in rupees.
4
4
  const data = Array.from({ length: 250 }, (_, i) => {
5
5
  const day = new Date(Date.UTC(2025, 9, 20 + Math.floor((i * 7) / 5)));
6
6
  return { time: day.toISOString().slice(0, 10), value: 1500 + i * 1.2 + Math.sin(i / 9) * 60 + Math.sin(i / 3) * 18 };
@@ -10,14 +10,14 @@ export default function PriceChartExample() {
10
10
  return (
11
11
  <Card>
12
12
  <CardHeader>
13
- <CardTitle>INFY</CardTitle>
14
- <CardDescription>Daily close, one year</CardDescription>
13
+ <CardTitle>Average order value</CardTitle>
14
+ <CardDescription>Daily, one year, ₹</CardDescription>
15
15
  </CardHeader>
16
16
  <CardContent>
17
17
  <PriceChart data={data} height={256} />
18
18
  </CardContent>
19
- <CardFooter className="text-xs text-muted-foreground">
20
- <span>
19
+ <CardFooter>
20
+ <span className="text-xs text-muted-foreground">
21
21
  Chart by{" "}
22
22
  <a
23
23
  className="text-link underline-offset-4 hover:underline"
@@ -1,22 +1,23 @@
1
1
  import { ToneProgress, useFormat } from "@siyahi/ui";
2
2
 
3
- const positions = [
4
- { symbol: "INFY", realized: 84200, share: 0.41 },
5
- { symbol: "ITC", realized: -61200, share: 0.3 },
6
- { symbol: "TCS", realized: 21000, share: 0.1 },
3
+ // Each sales channel's profit or loss this quarter, and its share of all the profit and loss booked; made-up figures.
4
+ const channels = [
5
+ { channel: "Online", profit: 84200, share: 0.41 },
6
+ { channel: "Retail", profit: -61200, share: 0.3 },
7
+ { channel: "Export", profit: 21000, share: 0.1 },
7
8
  ];
8
9
 
9
10
  export default function ProgressToneExample() {
10
11
  const { pct } = useFormat();
11
12
  return (
12
13
  <div className="flex max-w-sm flex-col gap-3 text-sm">
13
- {positions.map((p) => (
14
- <div key={p.symbol} className="flex items-center gap-3">
15
- <span className="w-16 font-medium">{p.symbol}</span>
14
+ {channels.map((p) => (
15
+ <div key={p.channel} className="flex items-center gap-3">
16
+ <span className="w-16 font-medium">{p.channel}</span>
16
17
  <ToneProgress
17
- tone={p.realized >= 0 ? "positive" : "negative"}
18
+ tone={p.profit >= 0 ? "positive" : "negative"}
18
19
  value={p.share * 100}
19
- aria-label={`${p.symbol}'s share of the booked P&L`}
20
+ aria-label={`${p.channel}'s share of the quarter's profit and loss`}
20
21
  getAriaValueText={() => pct(p.share)}
21
22
  className="w-24"
22
23
  />
@@ -3,7 +3,7 @@ import { Progress, ProgressLabel, ProgressValue } from "@siyahi/ui";
3
3
  export default function ProgressExample() {
4
4
  return (
5
5
  <Progress value={64} className="max-w-sm">
6
- <ProgressLabel>Statements imported</ProgressLabel>
6
+ <ProgressLabel>Orders imported</ProgressLabel>
7
7
  <ProgressValue />
8
8
  </Progress>
9
9
  );