@siyahi/ui 0.1.9-next.22 → 0.1.9-next.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +3 -2
- package/agents/examples/accordion.tsx +7 -7
- package/agents/examples/alert.tsx +16 -15
- package/agents/examples/badge.tsx +20 -12
- package/agents/examples/bar-list-labels.tsx +6 -6
- package/agents/examples/bar-list-sides.tsx +8 -8
- package/agents/examples/bar-list.tsx +8 -8
- package/agents/examples/breadcrumb.tsx +3 -3
- package/agents/examples/callout.tsx +15 -15
- package/agents/examples/card.tsx +3 -3
- package/agents/examples/change-bar.tsx +21 -21
- package/agents/examples/chart-area.tsx +11 -11
- package/agents/examples/chart-bar-flows.tsx +1 -1
- package/agents/examples/chart-bar-hourly.tsx +1 -1
- package/agents/examples/chart-bar-losses.tsx +3 -3
- package/agents/examples/chart-bar-teams.tsx +72 -0
- package/agents/examples/chart-bar-years.tsx +5 -5
- package/agents/examples/chart-bar.tsx +10 -10
- package/agents/examples/chart-category-ticks.tsx +6 -6
- package/agents/examples/chart-line.tsx +17 -17
- package/agents/examples/collapsible.tsx +4 -2
- package/agents/examples/command.tsx +6 -6
- package/agents/examples/context-menu.tsx +2 -2
- package/agents/examples/data-bar.tsx +32 -45
- package/agents/examples/data-table-compact.tsx +31 -30
- package/agents/examples/data-table-filters.tsx +20 -20
- package/agents/examples/data-table.tsx +31 -30
- package/agents/examples/delta.tsx +11 -6
- package/agents/examples/dialog.tsx +3 -3
- package/agents/examples/distribution-bar-tug.tsx +15 -15
- package/agents/examples/dropdown-menu.tsx +2 -2
- package/agents/examples/heatmap-calendar.tsx +6 -6
- package/agents/examples/heatmap-status.tsx +1 -1
- package/agents/examples/heatmap-weekday.tsx +7 -7
- package/agents/examples/input-states.tsx +9 -9
- package/agents/examples/input.tsx +3 -3
- package/agents/examples/local-time.tsx +1 -1
- package/agents/examples/metric-strip.tsx +8 -8
- package/agents/examples/page-hero.tsx +2 -2
- package/agents/examples/popover.tsx +3 -3
- package/agents/examples/price-chart.tsx +3 -3
- package/agents/examples/progress-tone.tsx +10 -9
- package/agents/examples/progress.tsx +1 -1
- package/agents/examples/range-position-table.tsx +31 -31
- package/agents/examples/range-position.tsx +18 -18
- package/agents/examples/section-cards-select.tsx +11 -10
- package/agents/examples/section-cards-trend.tsx +4 -4
- package/agents/examples/section-cards.tsx +13 -13
- package/agents/examples/select.tsx +9 -9
- package/agents/examples/separator.tsx +3 -3
- package/agents/examples/sheet.tsx +1 -1
- package/agents/examples/slider.tsx +1 -1
- package/agents/examples/surfaces.tsx +16 -18
- package/agents/examples/tabs.tsx +7 -7
- package/agents/examples/target-rows.tsx +25 -23
- package/agents/examples/tooltip.tsx +2 -2
- package/agents/examples/treemap.tsx +27 -24
- package/agents/manifest.json +15 -15
- package/dist/components/registry/charts/bar-chart-card.d.ts +1 -1
- package/dist/components/registry/charts/line-chart-card.d.ts +1 -1
- package/dist/components/registry/charts/line-chart-card.js +1 -1
- package/dist/components/siyahi/callout.d.ts +5 -12
- package/dist/components/siyahi/callout.js +5 -11
- package/dist/components/siyahi/delta.js +2 -2
- package/dist/components/siyahi/status-alert.d.ts +15 -0
- package/dist/components/siyahi/status-alert.js +29 -0
- package/dist/components/siyahi/status-badge.d.ts +15 -0
- package/dist/components/siyahi/status-badge.js +24 -0
- package/dist/components/siyahi/tone-progress.d.ts +1 -1
- package/dist/components/siyahi/tone-progress.js +1 -1
- package/dist/components/siyahi/treemap.d.ts +4 -4
- package/dist/components/siyahi/treemap.js +2 -2
- package/dist/index.d.ts +5 -4
- package/dist/index.js +3 -2
- package/dist/lib/chart-frame.js +1 -1
- package/dist/lib/chart-series.d.ts +1 -1
- package/dist/lib/tone.d.ts +36 -0
- package/dist/lib/tone.js +35 -0
- package/package.json +1 -1
- package/styles/siyahi.css +7 -5
- package/agents/examples/chart-bar-sectors.tsx +0 -72
- package/dist/components/siyahi/warning-alert.d.ts +0 -10
- package/dist/components/siyahi/warning-alert.js +0 -20
|
@@ -4,14 +4,14 @@ export default function SectionCardsTrendExample() {
|
|
|
4
4
|
const { money, moneyCompact } = useFormat();
|
|
5
5
|
const items: SectionCard[] = [
|
|
6
6
|
{
|
|
7
|
-
label: "
|
|
7
|
+
label: "Revenue",
|
|
8
8
|
value: money(4512300),
|
|
9
9
|
badge: <Delta value={0.031} />,
|
|
10
10
|
trend: <Sparkline data={[3820000, 3950000, 4110000, 4020000, 4380000, 4512300]} />,
|
|
11
11
|
detail: "Month-end, last six months",
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
|
-
label: "
|
|
14
|
+
label: "Cash flow this year",
|
|
15
15
|
value: moneyCompact(-61200),
|
|
16
16
|
badge: <Delta value={-61200} format="money" />,
|
|
17
17
|
// A run of losses: the meaning colour, not a chart slot.
|
|
@@ -19,11 +19,11 @@ export default function SectionCardsTrendExample() {
|
|
|
19
19
|
detail: "Running total since April",
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
|
-
label: "
|
|
22
|
+
label: "Gift cards this year",
|
|
23
23
|
value: moneyCompact(38400),
|
|
24
24
|
badge: <Delta value={0.18} />,
|
|
25
25
|
trend: <Sparkline data={[4100, 0, 12800, 3300, 9900, 8300]} variant="line" curve="linear" />,
|
|
26
|
-
detail: "
|
|
26
|
+
detail: "Sold each month",
|
|
27
27
|
},
|
|
28
28
|
];
|
|
29
29
|
return <SectionCards items={items} />;
|
|
@@ -4,38 +4,38 @@ export default function SectionCardsExample() {
|
|
|
4
4
|
const { money, moneyCompact } = useFormat();
|
|
5
5
|
const items: SectionCard[] = [
|
|
6
6
|
{
|
|
7
|
-
label: "
|
|
7
|
+
label: "Revenue",
|
|
8
8
|
value: money(4512300),
|
|
9
9
|
badge: <Delta value={0.031} />,
|
|
10
10
|
headline: "Up for the third month",
|
|
11
|
-
detail: "
|
|
11
|
+
detail: "Paid orders, less refunds",
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
|
-
label: "
|
|
14
|
+
label: "Target",
|
|
15
15
|
value: money(4025000),
|
|
16
|
-
headline: "
|
|
17
|
-
detail: "Across 4
|
|
16
|
+
headline: "Set at the start of the quarter",
|
|
17
|
+
detail: "Across 4 stores",
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
|
-
label: "
|
|
20
|
+
label: "Ahead of target",
|
|
21
21
|
value: moneyCompact(487300),
|
|
22
22
|
badge: <Delta value={0.121} />,
|
|
23
|
-
headline: "
|
|
24
|
-
detail: "Since
|
|
23
|
+
headline: "Gross margin 14.2%",
|
|
24
|
+
detail: "Since April",
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
|
-
label: "
|
|
27
|
+
label: "Cash flow this year",
|
|
28
28
|
value: moneyCompact(-61200),
|
|
29
29
|
badge: <Delta value={-61200} format="money" />,
|
|
30
|
-
headline: "Two
|
|
30
|
+
headline: "Two large inventory buys",
|
|
31
31
|
detail: "Before tax",
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
|
-
label: "
|
|
34
|
+
label: "Gift cards this year",
|
|
35
35
|
value: moneyCompact(38400),
|
|
36
36
|
badge: <Delta value={0.18} />,
|
|
37
|
-
headline: "
|
|
38
|
-
detail: "
|
|
37
|
+
headline: "Sold in 11 stores",
|
|
38
|
+
detail: "Paid at purchase",
|
|
39
39
|
},
|
|
40
40
|
];
|
|
41
41
|
return (
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@siyahi/ui";
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
{ label: "All
|
|
5
|
-
{ label: "
|
|
6
|
-
{ label: "
|
|
7
|
-
{ label: "
|
|
3
|
+
const stores = [
|
|
4
|
+
{ label: "All stores", value: "all" },
|
|
5
|
+
{ label: "Online", value: "online" },
|
|
6
|
+
{ label: "Retail", value: "retail" },
|
|
7
|
+
{ label: "Wholesale", value: "wholesale" },
|
|
8
8
|
];
|
|
9
9
|
|
|
10
10
|
export default function SelectExample() {
|
|
11
11
|
return (
|
|
12
|
-
<Select items={
|
|
12
|
+
<Select items={stores} defaultValue="all">
|
|
13
13
|
<SelectTrigger className="w-48">
|
|
14
14
|
<SelectValue />
|
|
15
15
|
</SelectTrigger>
|
|
16
16
|
<SelectContent>
|
|
17
17
|
<SelectGroup>
|
|
18
|
-
{
|
|
19
|
-
<SelectItem key={
|
|
20
|
-
{
|
|
18
|
+
{stores.map((store) => (
|
|
19
|
+
<SelectItem key={store.value} value={store.value}>
|
|
20
|
+
{store.label}
|
|
21
21
|
</SelectItem>
|
|
22
22
|
))}
|
|
23
23
|
</SelectGroup>
|
|
@@ -3,11 +3,11 @@ import { Separator } from "@siyahi/ui";
|
|
|
3
3
|
export default function SeparatorExample() {
|
|
4
4
|
return (
|
|
5
5
|
<div className="flex h-6 items-center gap-4 text-sm">
|
|
6
|
-
<span>
|
|
6
|
+
<span>Orders</span>
|
|
7
7
|
<Separator orientation="vertical" />
|
|
8
|
-
<span>
|
|
8
|
+
<span>Customers</span>
|
|
9
9
|
<Separator orientation="vertical" />
|
|
10
|
-
<span>
|
|
10
|
+
<span>Products</span>
|
|
11
11
|
</div>
|
|
12
12
|
);
|
|
13
13
|
}
|
|
@@ -7,7 +7,7 @@ export default function SheetExample() {
|
|
|
7
7
|
<SheetContent>
|
|
8
8
|
<SheetHeader>
|
|
9
9
|
<SheetTitle>Filters</SheetTitle>
|
|
10
|
-
<SheetDescription>Narrow the
|
|
10
|
+
<SheetDescription>Narrow the orders by store, status or date.</SheetDescription>
|
|
11
11
|
</SheetHeader>
|
|
12
12
|
</SheetContent>
|
|
13
13
|
</Sheet>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Slider } from "@siyahi/ui";
|
|
2
2
|
|
|
3
3
|
export default function SliderExample() {
|
|
4
|
-
return <Slider defaultValue={[20, 80]} max={100} step={5} aria-label="
|
|
4
|
+
return <Slider defaultValue={[20, 80]} max={100} step={5} aria-label="Price range" className="max-w-sm" />;
|
|
5
5
|
}
|
|
@@ -32,19 +32,19 @@ const orders = [
|
|
|
32
32
|
{ hour: 15, orders: 38 },
|
|
33
33
|
];
|
|
34
34
|
|
|
35
|
-
const
|
|
36
|
-
{
|
|
37
|
-
{
|
|
38
|
-
{
|
|
35
|
+
const products = [
|
|
36
|
+
{ product: "Dinner set", revenue: 276000 },
|
|
37
|
+
{ product: "Standing desk", revenue: 224400 },
|
|
38
|
+
{ product: "Bookshelf", revenue: 166000 },
|
|
39
39
|
];
|
|
40
40
|
|
|
41
41
|
function Dashboard() {
|
|
42
42
|
const { money, moneyCompact, pct } = useFormat();
|
|
43
43
|
const kpis: MetricStripItem[] = [
|
|
44
|
-
{ label: "
|
|
45
|
-
{ label: "
|
|
46
|
-
{ label: "
|
|
47
|
-
{ label: "
|
|
44
|
+
{ label: "Revenue", value: money(4512300), change: 0.031 },
|
|
45
|
+
{ label: "Target", value: moneyCompact(4025000), change: 85000, changeFormat: "money" },
|
|
46
|
+
{ label: "Gross margin", value: pct(0.142), change: -0.004 },
|
|
47
|
+
{ label: "Cash flow", value: moneyCompact(-61200), change: -61200, changeFormat: "money" },
|
|
48
48
|
];
|
|
49
49
|
return (
|
|
50
50
|
<div className="flex flex-col gap-6">
|
|
@@ -61,24 +61,22 @@ function Dashboard() {
|
|
|
61
61
|
/>
|
|
62
62
|
<Card>
|
|
63
63
|
<CardHeader>
|
|
64
|
-
<CardTitle>
|
|
65
|
-
<CardDescription>Largest three</CardDescription>
|
|
64
|
+
<CardTitle>Top products</CardTitle>
|
|
65
|
+
<CardDescription>Largest three by revenue</CardDescription>
|
|
66
66
|
</CardHeader>
|
|
67
67
|
<CardContent>
|
|
68
68
|
<Table>
|
|
69
69
|
<TableHeader>
|
|
70
70
|
<TableRow>
|
|
71
|
-
<TableHead>
|
|
72
|
-
<TableHead>
|
|
71
|
+
<TableHead>Product</TableHead>
|
|
72
|
+
<TableHead>Revenue</TableHead>
|
|
73
73
|
</TableRow>
|
|
74
74
|
</TableHeader>
|
|
75
75
|
<TableBody>
|
|
76
|
-
{
|
|
77
|
-
<TableRow key={row.
|
|
78
|
-
<TableCell>
|
|
79
|
-
|
|
80
|
-
</TableCell>
|
|
81
|
-
<TableCell>{money(row.value)}</TableCell>
|
|
76
|
+
{products.map((row) => (
|
|
77
|
+
<TableRow key={row.product}>
|
|
78
|
+
<TableCell>{row.product}</TableCell>
|
|
79
|
+
<TableCell>{money(row.revenue)}</TableCell>
|
|
82
80
|
</TableRow>
|
|
83
81
|
))}
|
|
84
82
|
</TableBody>
|
package/agents/examples/tabs.tsx
CHANGED
|
@@ -2,15 +2,15 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@siyahi/ui";
|
|
|
2
2
|
|
|
3
3
|
export default function TabsExample() {
|
|
4
4
|
return (
|
|
5
|
-
<Tabs defaultValue="
|
|
5
|
+
<Tabs defaultValue="orders">
|
|
6
6
|
<TabsList>
|
|
7
|
-
<TabsTrigger value="
|
|
8
|
-
<TabsTrigger value="
|
|
9
|
-
<TabsTrigger value="
|
|
7
|
+
<TabsTrigger value="orders">Orders</TabsTrigger>
|
|
8
|
+
<TabsTrigger value="returns">Returns</TabsTrigger>
|
|
9
|
+
<TabsTrigger value="payouts">Payouts</TabsTrigger>
|
|
10
10
|
</TabsList>
|
|
11
|
-
<TabsContent value="
|
|
12
|
-
<TabsContent value="
|
|
13
|
-
<TabsContent value="
|
|
11
|
+
<TabsContent value="orders">Every order placed, newest first.</TabsContent>
|
|
12
|
+
<TabsContent value="returns">Items sent back and the refunds paid for them.</TabsContent>
|
|
13
|
+
<TabsContent value="payouts">Money paid out to sellers each week.</TabsContent>
|
|
14
14
|
</Tabs>
|
|
15
15
|
);
|
|
16
16
|
}
|
|
@@ -10,59 +10,61 @@ import {
|
|
|
10
10
|
type TargetStatus,
|
|
11
11
|
} from "@siyahi/ui";
|
|
12
12
|
|
|
13
|
-
interface
|
|
13
|
+
interface Team {
|
|
14
14
|
name: string;
|
|
15
|
-
|
|
16
|
-
/**
|
|
15
|
+
costs: string;
|
|
16
|
+
/** The team's share of this year's spend so far and the budget's share, as fractions; made-up figures. */
|
|
17
17
|
weight: number;
|
|
18
18
|
target: number;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const
|
|
22
|
-
{ name: "
|
|
23
|
-
{ name: "
|
|
24
|
-
{ name: "
|
|
25
|
-
{ name: "
|
|
26
|
-
{ name: "
|
|
21
|
+
const teams: Team[] = [
|
|
22
|
+
{ name: "Engineering", costs: "Cloud hosting, tools, contractors", weight: 0.426, target: 0.4 },
|
|
23
|
+
{ name: "Marketing", costs: "Ads, events, design agency", weight: 0.189, target: 0.2 },
|
|
24
|
+
{ name: "Sales", costs: "Travel, commissions, CRM seats", weight: 0.194, target: 0.25 },
|
|
25
|
+
{ name: "Support", costs: "Help desk seats, training", weight: 0.093, target: 0.1 },
|
|
26
|
+
{ name: "Operations", costs: "Office rent, facilities", weight: 0.098, target: 0.05 },
|
|
27
27
|
];
|
|
28
28
|
|
|
29
|
-
// Within two points of the
|
|
29
|
+
// Within two points of the budget is on target; past five is far enough to review it.
|
|
30
30
|
const NEAR = 0.02;
|
|
31
31
|
const FAR = 0.05;
|
|
32
32
|
|
|
33
33
|
const pts = (value: number) => `${(value * 100).toFixed(1)} pts`;
|
|
34
34
|
|
|
35
|
-
function statusOf({ weight, target }:
|
|
35
|
+
function statusOf({ weight, target }: Team): TargetStatus {
|
|
36
36
|
const gap = weight - target;
|
|
37
37
|
const size = `${pts(Math.abs(gap))} ${gap > 0 ? "over" : "under"}`;
|
|
38
38
|
if (Math.abs(gap) <= NEAR) return { kind: "met", label: "On target" };
|
|
39
39
|
if (Math.abs(gap) <= FAR) return { kind: "missed", label: size };
|
|
40
|
-
return { kind: "warning", label: `${size},
|
|
40
|
+
return { kind: "warning", label: `${size}, review` };
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export default function TargetRowsExample() {
|
|
44
44
|
const f = useFormat();
|
|
45
|
-
const rows: TargetRow[] =
|
|
46
|
-
label:
|
|
47
|
-
detail:
|
|
48
|
-
value:
|
|
49
|
-
target:
|
|
45
|
+
const rows: TargetRow[] = teams.map((team) => ({
|
|
46
|
+
label: team.name,
|
|
47
|
+
detail: team.costs,
|
|
48
|
+
value: team.weight,
|
|
49
|
+
target: team.target,
|
|
50
50
|
bands: [
|
|
51
|
-
[
|
|
52
|
-
[
|
|
51
|
+
[team.target - FAR, team.target + FAR],
|
|
52
|
+
[team.target - NEAR, team.target + NEAR],
|
|
53
53
|
],
|
|
54
|
-
status: statusOf(
|
|
54
|
+
status: statusOf(team),
|
|
55
55
|
}));
|
|
56
56
|
return (
|
|
57
57
|
<Card>
|
|
58
58
|
<CardHeader>
|
|
59
|
-
<CardTitle>
|
|
60
|
-
<CardDescription>
|
|
59
|
+
<CardTitle>Sales is 5.6 points under its budget</CardTitle>
|
|
60
|
+
<CardDescription>
|
|
61
|
+
Each team's share of spend against its share of the budget, on one 0–50% scale
|
|
62
|
+
</CardDescription>
|
|
61
63
|
</CardHeader>
|
|
62
64
|
<CardContent>
|
|
63
65
|
<div className="grid gap-2">
|
|
64
66
|
<p className="text-sm text-muted-foreground">
|
|
65
|
-
Bar:
|
|
67
|
+
Bar: the share spent so far. Tall tick: the budgeted share. Shading: within 5 points of it, darker within 2.
|
|
66
68
|
</p>
|
|
67
69
|
<TargetRows rows={rows} domain={[0, 0.5]} valueFormatter={(value) => f.pct(value)} />
|
|
68
70
|
</div>
|
|
@@ -4,10 +4,10 @@ import { InfoIcon } from "lucide-react";
|
|
|
4
4
|
export default function TooltipExample() {
|
|
5
5
|
return (
|
|
6
6
|
<Tooltip>
|
|
7
|
-
<TooltipTrigger render={<Button variant="outline" size="icon" aria-label="About
|
|
7
|
+
<TooltipTrigger render={<Button variant="outline" size="icon" aria-label="About churn" />}>
|
|
8
8
|
<InfoIcon />
|
|
9
9
|
</TooltipTrigger>
|
|
10
|
-
<TooltipContent>
|
|
10
|
+
<TooltipContent>Churn counts customers who did not renew this month.</TooltipContent>
|
|
11
11
|
</Tooltip>
|
|
12
12
|
);
|
|
13
13
|
}
|
|
@@ -14,42 +14,45 @@ import {
|
|
|
14
14
|
} from "@siyahi/ui";
|
|
15
15
|
import { useState } from "react";
|
|
16
16
|
|
|
17
|
-
interface
|
|
18
|
-
|
|
17
|
+
interface City extends TreemapItem {
|
|
18
|
+
channel: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
{ name: "
|
|
25
|
-
{ name: "
|
|
26
|
-
{ name: "
|
|
27
|
-
{ name: "
|
|
28
|
-
{ name: "
|
|
29
|
-
{ name: "
|
|
30
|
-
{ name: "
|
|
31
|
-
{ name: "
|
|
32
|
-
{ name: "
|
|
33
|
-
{ name: "
|
|
21
|
+
// weight is the month's sales in ₹ and change their growth on the same month last year; Guwahati opened this year,
|
|
22
|
+
// so it has no last year to grow from. Mumbai sells online and in stores, so it draws two tiles under one name.
|
|
23
|
+
const cities: City[] = [
|
|
24
|
+
{ name: "Mumbai", key: "mumbai-online", channel: "Online", group: "West", weight: 224400, change: 0.38 },
|
|
25
|
+
{ name: "Mumbai", key: "mumbai-stores", channel: "Stores", group: "West", weight: 152000, change: 0.12 },
|
|
26
|
+
{ name: "Pune", channel: "Stores", group: "West", weight: 166000, change: 0.09 },
|
|
27
|
+
{ name: "Surat", channel: "Online", group: "West", weight: 98000, change: -0.21 },
|
|
28
|
+
{ name: "Bengaluru", channel: "Stores", group: "South", weight: 262500, change: -0.06 },
|
|
29
|
+
{ name: "Chennai", channel: "Stores", group: "South", weight: 258000, change: 0.44 },
|
|
30
|
+
{ name: "Kochi", channel: "Online", group: "South", weight: 87000, change: 0.58 },
|
|
31
|
+
{ name: "Delhi", channel: "Stores", group: "North", weight: 276000, change: 0.27 },
|
|
32
|
+
{ name: "Jaipur", channel: "Online", group: "North", weight: 64000, change: -0.33 },
|
|
33
|
+
{ name: "Kolkata", channel: "Stores", group: "East", weight: 255600, change: 0.16 },
|
|
34
|
+
{ name: "Guwahati", channel: "Online", group: "Northeast", weight: 52000, change: null },
|
|
34
35
|
];
|
|
35
36
|
|
|
36
37
|
export default function TreemapExample() {
|
|
37
|
-
const [hovered, setHovered] = useState<
|
|
38
|
-
const [selected, setSelected] = useState<
|
|
38
|
+
const [hovered, setHovered] = useState<City | null>(null);
|
|
39
|
+
const [selected, setSelected] = useState<City | null>(null);
|
|
39
40
|
const { money, pct } = useFormat();
|
|
40
|
-
const figures = (
|
|
41
|
-
`${money(
|
|
41
|
+
const figures = (c: City) =>
|
|
42
|
+
`${money(c.weight)} · ${c.change === null ? "new this year" : `${c.change < 0 ? "\u2212" : "+"}${pct(Math.abs(c.change))}`}`;
|
|
42
43
|
return (
|
|
43
44
|
<Card>
|
|
44
45
|
<CardHeader>
|
|
45
|
-
<CardTitle>
|
|
46
|
-
<CardDescription>
|
|
46
|
+
<CardTitle>Sales by region</CardTitle>
|
|
47
|
+
<CardDescription>
|
|
48
|
+
Area is the city's sales this month; colour is its growth on last year, deepest at ±60%
|
|
49
|
+
</CardDescription>
|
|
47
50
|
</CardHeader>
|
|
48
51
|
<CardContent>
|
|
49
52
|
<Tooltip open={hovered !== null} trackCursorAxis="both">
|
|
50
53
|
<TooltipTrigger render={<div />}>
|
|
51
54
|
<Treemap
|
|
52
|
-
items={
|
|
55
|
+
items={cities}
|
|
53
56
|
height={320}
|
|
54
57
|
range={0.6}
|
|
55
58
|
onHover={setHovered}
|
|
@@ -62,7 +65,7 @@ export default function TreemapExample() {
|
|
|
62
65
|
{hovered && (
|
|
63
66
|
<>
|
|
64
67
|
<span className="font-medium">
|
|
65
|
-
{hovered.name} · {hovered.
|
|
68
|
+
{hovered.name} · {hovered.channel}
|
|
66
69
|
</span>
|
|
67
70
|
<span>{hovered.group}</span>
|
|
68
71
|
<span>{figures(hovered)}</span>
|
|
@@ -76,7 +79,7 @@ export default function TreemapExample() {
|
|
|
76
79
|
{selected ? (
|
|
77
80
|
<>
|
|
78
81
|
<span className="font-medium">
|
|
79
|
-
{selected.name} · {selected.
|
|
82
|
+
{selected.name} · {selected.channel}
|
|
80
83
|
</span>{" "}
|
|
81
84
|
· {selected.group} · {figures(selected)}
|
|
82
85
|
</>
|
package/agents/manifest.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"needs": [
|
|
18
18
|
{
|
|
19
|
-
"need": "Values over time or another ordered axis (months, hours,
|
|
19
|
+
"need": "Values over time or another ordered axis (months, hours, size buckets)",
|
|
20
20
|
"guidance": "`BarChartCard`, `AreaChartCard` or `LineChartCard`",
|
|
21
21
|
"components": [
|
|
22
22
|
"BarChartCard",
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
]
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
|
-
"need": "A running level, such as
|
|
35
|
+
"need": "A running level, such as revenue against its target",
|
|
36
36
|
"guidance": "`AreaChartCard`",
|
|
37
37
|
"components": [
|
|
38
38
|
"AreaChartCard"
|
|
39
39
|
]
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
|
-
"need": "Series compared point by point, such as
|
|
42
|
+
"need": "Series compared point by point, such as growth against a benchmark",
|
|
43
43
|
"guidance": "`LineChartCard`",
|
|
44
44
|
"components": [
|
|
45
45
|
"LineChartCard"
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
]
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
|
-
"need": "Long category names, such as
|
|
56
|
+
"need": "Long category names, such as teams or product categories",
|
|
57
57
|
"guidance": "`BarChartCard` with `horizontal`",
|
|
58
58
|
"components": [
|
|
59
59
|
"BarChartCard"
|
|
@@ -118,28 +118,28 @@
|
|
|
118
118
|
]
|
|
119
119
|
},
|
|
120
120
|
{
|
|
121
|
-
"need": "Figures against their targets, such as
|
|
121
|
+
"need": "Figures against their targets, such as spend against budget",
|
|
122
122
|
"guidance": "`TargetRows`, with neutral `bands` and a `status` per row",
|
|
123
123
|
"components": [
|
|
124
124
|
"TargetRows"
|
|
125
125
|
]
|
|
126
126
|
},
|
|
127
127
|
{
|
|
128
|
-
"need": "Where a value sits in its range, such as
|
|
128
|
+
"need": "Where a value sits in its range, such as today's response time in its 30-day range",
|
|
129
129
|
"guidance": "`RangePosition`; `variant=\"compact\"` in a table cell",
|
|
130
130
|
"components": [
|
|
131
131
|
"RangePosition"
|
|
132
132
|
]
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
|
-
"need": "
|
|
135
|
+
"need": "A long daily series, such as a price or an order value",
|
|
136
136
|
"guidance": "`PriceChart`",
|
|
137
137
|
"components": [
|
|
138
138
|
"PriceChart"
|
|
139
139
|
]
|
|
140
140
|
},
|
|
141
141
|
{
|
|
142
|
-
"need": "
|
|
142
|
+
"need": "Items sized by weight and coloured by change, such as sales by city",
|
|
143
143
|
"guidance": "`Treemap`",
|
|
144
144
|
"components": [
|
|
145
145
|
"Treemap"
|
|
@@ -304,10 +304,9 @@
|
|
|
304
304
|
{
|
|
305
305
|
"file": "agents/examples/alert.tsx",
|
|
306
306
|
"components": [
|
|
307
|
-
"Alert",
|
|
308
307
|
"AlertDescription",
|
|
309
308
|
"AlertTitle",
|
|
310
|
-
"
|
|
309
|
+
"StatusAlert"
|
|
311
310
|
]
|
|
312
311
|
},
|
|
313
312
|
{
|
|
@@ -328,7 +327,8 @@
|
|
|
328
327
|
"file": "agents/examples/badge.tsx",
|
|
329
328
|
"components": [
|
|
330
329
|
"Badge",
|
|
331
|
-
"Delta"
|
|
330
|
+
"Delta",
|
|
331
|
+
"StatusBadge"
|
|
332
332
|
]
|
|
333
333
|
},
|
|
334
334
|
{
|
|
@@ -401,11 +401,11 @@
|
|
|
401
401
|
{
|
|
402
402
|
"file": "agents/examples/callout.tsx",
|
|
403
403
|
"components": [
|
|
404
|
+
"AlertDescription",
|
|
405
|
+
"AlertTitle",
|
|
404
406
|
"Callout",
|
|
405
407
|
"Quote",
|
|
406
|
-
"
|
|
407
|
-
"AlertDescription",
|
|
408
|
-
"AlertTitle"
|
|
408
|
+
"StatusAlert"
|
|
409
409
|
]
|
|
410
410
|
},
|
|
411
411
|
{
|
|
@@ -472,7 +472,7 @@
|
|
|
472
472
|
]
|
|
473
473
|
},
|
|
474
474
|
{
|
|
475
|
-
"file": "agents/examples/chart-bar-
|
|
475
|
+
"file": "agents/examples/chart-bar-teams.tsx",
|
|
476
476
|
"components": [
|
|
477
477
|
"BarChartCard",
|
|
478
478
|
"ToggleGroup",
|
|
@@ -3,7 +3,7 @@ import { SeriesChartProps } from "../../../lib/chart-series.js";
|
|
|
3
3
|
export interface BarChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K> {
|
|
4
4
|
/** Stack the series in one bar per point instead of side by side. */
|
|
5
5
|
stacked?: boolean;
|
|
6
|
-
/** Bars run sideways, categories down the left: for long names, such as
|
|
6
|
+
/** Bars run sideways, categories down the left: for long names, such as product categories. */
|
|
7
7
|
horizontal?: boolean;
|
|
8
8
|
/** The picked category's x value: its bars stay solid and the rest fade. */
|
|
9
9
|
selected?: T[K] | null;
|
|
@@ -3,6 +3,6 @@ import { ChartCurve, NumericXProps, SeriesChartProps } from "../../../lib/chart-
|
|
|
3
3
|
export interface LineChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps {
|
|
4
4
|
curve?: ChartCurve;
|
|
5
5
|
}
|
|
6
|
-
/** Values over an ordered axis as lines: one series, or several to compare, such as
|
|
6
|
+
/** Values over an ordered axis as lines: one series, or several to compare, such as sales against a target. */
|
|
7
7
|
export declare function LineChartCard<T extends object, K extends keyof T>({ curve, ...props }: LineChartCardProps<T, K>): import("react").JSX.Element;
|
|
8
8
|
//#endregion
|
|
@@ -3,7 +3,7 @@ import { ChartFrame, endDot } from "../../../lib/chart-frame.js";
|
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
import { Line, LineChart } from "recharts";
|
|
5
5
|
//#region src/components/registry/charts/line-chart-card.tsx
|
|
6
|
-
/** Values over an ordered axis as lines: one series, or several to compare, such as
|
|
6
|
+
/** Values over an ordered axis as lines: one series, or several to compare, such as sales against a target. */
|
|
7
7
|
function LineChartCard({ curve = "monotone", ...props }) {
|
|
8
8
|
return /* @__PURE__ */ jsx(ChartFrame, {
|
|
9
9
|
chart: LineChart,
|
|
@@ -1,24 +1,17 @@
|
|
|
1
|
+
import { Tone } from "../../lib/tone.js";
|
|
1
2
|
import { ComponentProps, ReactNode } from "react";
|
|
2
3
|
//#region src/components/siyahi/callout.d.ts
|
|
3
|
-
declare const TONES: {
|
|
4
|
-
readonly neutral: "border-border bg-muted/50 [&_[data-slot=callout-icon]]:text-muted-foreground";
|
|
5
|
-
readonly accent: "border-chart-1/35 bg-chart-1/8 [&_[data-slot=callout-icon]]:text-link";
|
|
6
|
-
readonly warning: "border-warning/45 bg-warning/10 [&_[data-slot=callout-icon]]:text-warning";
|
|
7
|
-
readonly positive: "border-positive/40 bg-positive/8 [&_[data-slot=callout-icon]]:text-positive";
|
|
8
|
-
readonly negative: "border-negative/40 bg-negative/8 [&_[data-slot=callout-icon]]:text-negative";
|
|
9
|
-
};
|
|
10
4
|
export interface CalloutProps extends Omit<ComponentProps<"aside">, "title"> {
|
|
11
5
|
/** neutral for an aside, accent for a key point, warning for a caution, positive or negative for a gain or a loss. */
|
|
12
|
-
tone?:
|
|
6
|
+
tone?: Tone;
|
|
13
7
|
/** A lucide icon, drawn in the tone's colour. */
|
|
14
8
|
icon?: ReactNode;
|
|
15
9
|
title?: ReactNode;
|
|
16
10
|
}
|
|
17
11
|
/**
|
|
18
12
|
* A point set apart from the prose: a takeaway, a caveat, a definition. The whole box takes the tone, a faint wash
|
|
19
|
-
* inside a border of the same colour; never a single coloured edge. For a notice that interrupts, use
|
|
20
|
-
*
|
|
13
|
+
* inside a border of the same colour; never a single coloured edge. For a notice that interrupts, use StatusAlert
|
|
14
|
+
* instead.
|
|
21
15
|
*/
|
|
22
16
|
export declare function Callout({ tone, icon, title, className, children, ...props }: CalloutProps): import("react").JSX.Element;
|
|
23
|
-
//#endregion
|
|
24
|
-
export {};
|
|
17
|
+
//#endregion
|
|
@@ -1,28 +1,22 @@
|
|
|
1
|
+
import { TONES } from "../../lib/tone.js";
|
|
1
2
|
import { cn } from "cn";
|
|
2
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
4
|
//#region src/components/siyahi/callout.tsx
|
|
4
|
-
const TONES = {
|
|
5
|
-
neutral: "border-border bg-muted/50 [&_[data-slot=callout-icon]]:text-muted-foreground",
|
|
6
|
-
accent: "border-chart-1/35 bg-chart-1/8 [&_[data-slot=callout-icon]]:text-link",
|
|
7
|
-
warning: "border-warning/45 bg-warning/10 [&_[data-slot=callout-icon]]:text-warning",
|
|
8
|
-
positive: "border-positive/40 bg-positive/8 [&_[data-slot=callout-icon]]:text-positive",
|
|
9
|
-
negative: "border-negative/40 bg-negative/8 [&_[data-slot=callout-icon]]:text-negative"
|
|
10
|
-
};
|
|
11
5
|
/**
|
|
12
6
|
* A point set apart from the prose: a takeaway, a caveat, a definition. The whole box takes the tone, a faint wash
|
|
13
|
-
* inside a border of the same colour; never a single coloured edge. For a notice that interrupts, use
|
|
14
|
-
*
|
|
7
|
+
* inside a border of the same colour; never a single coloured edge. For a notice that interrupts, use StatusAlert
|
|
8
|
+
* instead.
|
|
15
9
|
*/
|
|
16
10
|
function Callout({ tone = "neutral", icon, title, className, children, ...props }) {
|
|
17
11
|
return /* @__PURE__ */ jsxs("aside", {
|
|
18
12
|
"data-slot": "callout",
|
|
19
13
|
"data-tone": tone,
|
|
20
|
-
className: cn("flex gap-3 rounded-lg border px-4 py-3 text-sm", TONES[tone], className),
|
|
14
|
+
className: cn("flex gap-3 rounded-lg border px-4 py-3 text-sm", TONES[tone].box, className),
|
|
21
15
|
...props,
|
|
22
16
|
children: [icon && /* @__PURE__ */ jsx("span", {
|
|
23
17
|
"data-slot": "callout-icon",
|
|
24
18
|
"aria-hidden": true,
|
|
25
|
-
className: "mt-0.5 shrink-0 [&>svg]:size-4",
|
|
19
|
+
className: cn("mt-0.5 shrink-0 [&>svg]:size-4", TONES[tone].ink),
|
|
26
20
|
children: icon
|
|
27
21
|
}), /* @__PURE__ */ jsxs("div", {
|
|
28
22
|
className: "flex min-w-0 flex-col gap-1",
|