@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
package/DESIGN.md
CHANGED
|
@@ -17,7 +17,8 @@ a meaning:
|
|
|
17
17
|
`+` or `−`, and only a small trend icon in green or red. In plain text (labels, tooltips) write the sign; never
|
|
18
18
|
colour a run of figures green and red.
|
|
19
19
|
**Amber** means caution. None of them decorates.
|
|
20
|
-
- **Emphasis tints the whole surface.** A
|
|
20
|
+
- **Emphasis tints the whole surface.** A notice is `StatusAlert` in its tone (an
|
|
21
|
+
error reads like a warning, only red); a state is `StatusBadge`; a point set
|
|
21
22
|
apart is `Callout` (`neutral`, `accent`, `warning`, `positive`,
|
|
22
23
|
`negative`); a quotation is `Quote`. Each takes a faint wash of its colour
|
|
23
24
|
inside a 1px border of the same colour all round. Large marks follow the same
|
|
@@ -37,6 +38,6 @@ a meaning:
|
|
|
37
38
|
- **Destructive is not loss.** `--destructive` (delete, an invalid field) is a
|
|
38
39
|
deeper red than `--negative` (a loss figure), so its label reads on its own
|
|
39
40
|
tint; never use one for the other.
|
|
40
|
-
- Categories (a
|
|
41
|
+
- Categories (a team, a region, a product line) stay neutral: outline badges,
|
|
41
42
|
never a hue each. Ordered buckets (largest 5, next 5, rest) use steps of one
|
|
42
43
|
colour, not separate hues.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@siyahi/ui";
|
|
2
2
|
|
|
3
3
|
const questions = [
|
|
4
|
+
["refresh", "When are the figures refreshed?", "Every night at midnight IST, and every minute for today's orders."],
|
|
4
5
|
[
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
6
|
+
"refunds",
|
|
7
|
+
"How are refunds counted?",
|
|
8
|
+
"A refund comes off the month the order was placed in, not the month it was paid.",
|
|
8
9
|
],
|
|
9
|
-
["
|
|
10
|
-
["brokers", "Can I add a second broker?", "Yes. Each broker is its own account, and the totals add them up."],
|
|
10
|
+
["stores", "Can I add a second store?", "Yes. Each store is its own workspace, and the totals add them up."],
|
|
11
11
|
] as const;
|
|
12
12
|
|
|
13
13
|
function Questions() {
|
|
@@ -24,13 +24,13 @@ export default function AccordionExample() {
|
|
|
24
24
|
<div className="grid gap-6 md:grid-cols-2">
|
|
25
25
|
<div className="flex flex-col gap-2">
|
|
26
26
|
<p className="text-sm text-muted-foreground">One open at a time</p>
|
|
27
|
-
<Accordion aria-label="One open at a time" defaultValue={["
|
|
27
|
+
<Accordion aria-label="One open at a time" defaultValue={["refresh"]}>
|
|
28
28
|
<Questions />
|
|
29
29
|
</Accordion>
|
|
30
30
|
</div>
|
|
31
31
|
<div className="flex flex-col gap-2">
|
|
32
32
|
<p className="text-sm text-muted-foreground">Several open</p>
|
|
33
|
-
<Accordion aria-label="Several open" multiple defaultValue={["
|
|
33
|
+
<Accordion aria-label="Several open" multiple defaultValue={["refresh", "refunds"]}>
|
|
34
34
|
<Questions />
|
|
35
35
|
</Accordion>
|
|
36
36
|
</div>
|
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CircleAlertIcon, InfoIcon } from "lucide-react";
|
|
1
|
+
import { AlertDescription, AlertTitle, StatusAlert } from "@siyahi/ui";
|
|
3
2
|
|
|
4
3
|
export default function AlertExample() {
|
|
5
4
|
return (
|
|
6
5
|
<div className="flex flex-col gap-3">
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<Alert variant="destructive">
|
|
17
|
-
<CircleAlertIcon />
|
|
6
|
+
<StatusAlert>
|
|
7
|
+
<AlertTitle>Figures are delayed</AlertTitle>
|
|
8
|
+
<AlertDescription>Sales figures refresh every fifteen minutes during opening hours.</AlertDescription>
|
|
9
|
+
</StatusAlert>
|
|
10
|
+
<StatusAlert tone="warning">
|
|
11
|
+
<AlertTitle>Two payments are unmatched</AlertTitle>
|
|
12
|
+
<AlertDescription>The bank statement lists payments no order accounts for yet.</AlertDescription>
|
|
13
|
+
</StatusAlert>
|
|
14
|
+
<StatusAlert tone="negative">
|
|
18
15
|
<AlertTitle>Import failed</AlertTitle>
|
|
19
|
-
<AlertDescription>The
|
|
20
|
-
</
|
|
16
|
+
<AlertDescription>The CSV could not be read. Export it again and retry.</AlertDescription>
|
|
17
|
+
</StatusAlert>
|
|
18
|
+
<StatusAlert tone="positive">
|
|
19
|
+
<AlertTitle>Refunds are settled</AlertTitle>
|
|
20
|
+
<AlertDescription>All 14 refunds from last week have reached the customers' accounts.</AlertDescription>
|
|
21
|
+
</StatusAlert>
|
|
21
22
|
</div>
|
|
22
23
|
);
|
|
23
24
|
}
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
import { Badge, Delta } from "@siyahi/ui";
|
|
1
|
+
import { Badge, Delta, StatusBadge } from "@siyahi/ui";
|
|
2
2
|
|
|
3
3
|
export default function BadgeExample() {
|
|
4
4
|
return (
|
|
5
|
-
<div className="flex flex-
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<
|
|
12
|
-
</
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
|
|
5
|
+
<div className="flex flex-col gap-3">
|
|
6
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
7
|
+
<StatusBadge tone="positive">Paid</StatusBadge>
|
|
8
|
+
<StatusBadge tone="warning">Pending</StatusBadge>
|
|
9
|
+
<StatusBadge tone="negative">Failed</StatusBadge>
|
|
10
|
+
<StatusBadge tone="accent">New</StatusBadge>
|
|
11
|
+
<StatusBadge>Draft</StatusBadge>
|
|
12
|
+
</div>
|
|
13
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
14
|
+
<Badge>Active</Badge>
|
|
15
|
+
<Badge variant="secondary">Archived</Badge>
|
|
16
|
+
<Badge variant="outline">Engineering</Badge>
|
|
17
|
+
<Badge variant="outline">
|
|
18
|
+
<Delta value={0.042} />
|
|
19
|
+
</Badge>
|
|
20
|
+
<Badge variant="outline">
|
|
21
|
+
<Delta value={-0.013} />
|
|
22
|
+
</Badge>
|
|
23
|
+
</div>
|
|
16
24
|
</div>
|
|
17
25
|
);
|
|
18
26
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BarList, Card, CardContent, CardDescription, CardHeader, CardTitle, useFormat } from "@siyahi/ui";
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
{ name: "
|
|
5
|
-
{ name: "
|
|
6
|
-
{ name: "
|
|
3
|
+
const categories = [
|
|
4
|
+
{ name: "Home Appliances and Kitchen Equipment", value: 100 },
|
|
5
|
+
{ name: "Health, Beauty and Personal Care", value: 70 },
|
|
6
|
+
{ name: "Books, Stationery and Office Supplies", value: 50 },
|
|
7
7
|
];
|
|
8
8
|
|
|
9
9
|
export default function BarListLabelsExample() {
|
|
@@ -11,11 +11,11 @@ export default function BarListLabelsExample() {
|
|
|
11
11
|
return (
|
|
12
12
|
<Card>
|
|
13
13
|
<CardHeader>
|
|
14
|
-
<CardTitle>Orders by
|
|
14
|
+
<CardTitle>Orders by category, ranked</CardTitle>
|
|
15
15
|
<CardDescription>Full labels and order counts stay readable in narrow panels</CardDescription>
|
|
16
16
|
</CardHeader>
|
|
17
17
|
<CardContent>
|
|
18
|
-
<BarList data={
|
|
18
|
+
<BarList data={categories} valueFormatter={count} />
|
|
19
19
|
</CardContent>
|
|
20
20
|
</Card>
|
|
21
21
|
);
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { BarList, Card, CardContent, CardDescription, CardHeader, CardTitle, useFormat } from "@siyahi/ui";
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// This quarter's revenue against last quarter's, by city: the biggest rises and falls; made-up figures.
|
|
4
4
|
const gains = [
|
|
5
|
-
{ name: "
|
|
6
|
-
{ name: "
|
|
7
|
-
{ name: "
|
|
5
|
+
{ name: "Mumbai", value: 84000 },
|
|
6
|
+
{ name: "Bengaluru", value: 52000 },
|
|
7
|
+
{ name: "Pune", value: 31000 },
|
|
8
8
|
];
|
|
9
9
|
const losses = [
|
|
10
|
-
{ name: "
|
|
11
|
-
{ name: "
|
|
10
|
+
{ name: "Kolkata", value: 18400 },
|
|
11
|
+
{ name: "Jaipur", value: 7600 },
|
|
12
12
|
];
|
|
13
13
|
|
|
14
14
|
export default function BarListSidesExample() {
|
|
@@ -18,8 +18,8 @@ export default function BarListSidesExample() {
|
|
|
18
18
|
return (
|
|
19
19
|
<Card>
|
|
20
20
|
<CardHeader>
|
|
21
|
-
<CardTitle>What
|
|
22
|
-
<CardDescription>The biggest ₹
|
|
21
|
+
<CardTitle>What moved revenue</CardTitle>
|
|
22
|
+
<CardDescription>The biggest ₹ rises and falls by city, on one scale</CardDescription>
|
|
23
23
|
</CardHeader>
|
|
24
24
|
{/* Each list is a column of its own, headed and ruled off, with its figures at its own right edge, so a
|
|
25
25
|
gain's figure never reads as the label of the loss beside it. */}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { BarList, Card, CardContent, CardDescription, CardHeader, CardTitle, Delta, useFormat } from "@siyahi/ui";
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
const
|
|
5
|
-
{ name: "
|
|
6
|
-
{ name: "
|
|
7
|
-
{ name: "
|
|
8
|
-
{ name: "
|
|
3
|
+
// value is the drop in a customer's monthly spend; detail is that drop as a share of last month's.
|
|
4
|
+
const largestDrops = [
|
|
5
|
+
{ name: "Sharma Textiles", value: 18400, detail: <Delta value={-0.062} /> },
|
|
6
|
+
{ name: "Bluepine Logistics", value: 12900, detail: <Delta value={-0.047} /> },
|
|
7
|
+
{ name: "Lakeview Clinics", value: 7600, detail: <Delta value={-0.072} /> },
|
|
8
|
+
{ name: "Coastal Foods (India)", value: 4100, detail: <Delta value={-0.06} /> },
|
|
9
9
|
];
|
|
10
10
|
|
|
11
11
|
export default function BarListExample() {
|
|
@@ -14,10 +14,10 @@ export default function BarListExample() {
|
|
|
14
14
|
<Card>
|
|
15
15
|
<CardHeader>
|
|
16
16
|
<CardTitle>Needs attention</CardTitle>
|
|
17
|
-
<CardDescription>
|
|
17
|
+
<CardDescription>Customers whose spend fell most this month</CardDescription>
|
|
18
18
|
</CardHeader>
|
|
19
19
|
<CardContent>
|
|
20
|
-
<BarList data={
|
|
20
|
+
<BarList data={largestDrops} valueFormatter={(v) => money(v)} showPercentage />
|
|
21
21
|
</CardContent>
|
|
22
22
|
</Card>
|
|
23
23
|
);
|
|
@@ -12,15 +12,15 @@ export default function BreadcrumbExample() {
|
|
|
12
12
|
<Breadcrumb>
|
|
13
13
|
<BreadcrumbList>
|
|
14
14
|
<BreadcrumbItem>
|
|
15
|
-
<BreadcrumbLink href="#/components">
|
|
15
|
+
<BreadcrumbLink href="#/components">Projects</BreadcrumbLink>
|
|
16
16
|
</BreadcrumbItem>
|
|
17
17
|
<BreadcrumbSeparator />
|
|
18
18
|
<BreadcrumbItem>
|
|
19
|
-
<BreadcrumbLink href="#/components">
|
|
19
|
+
<BreadcrumbLink href="#/components">Website</BreadcrumbLink>
|
|
20
20
|
</BreadcrumbItem>
|
|
21
21
|
<BreadcrumbSeparator />
|
|
22
22
|
<BreadcrumbItem>
|
|
23
|
-
<BreadcrumbPage>
|
|
23
|
+
<BreadcrumbPage>Checkout redesign</BreadcrumbPage>
|
|
24
24
|
</BreadcrumbItem>
|
|
25
25
|
</BreadcrumbList>
|
|
26
26
|
</Breadcrumb>
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AlertDescription, AlertTitle, Callout, Quote, StatusAlert } from "@siyahi/ui";
|
|
2
2
|
import { LightbulbIcon, InfoIcon, TriangleAlertIcon, TrendingUpIcon, TrendingDownIcon } from "lucide-react";
|
|
3
3
|
|
|
4
4
|
export default function CalloutExample() {
|
|
5
5
|
return (
|
|
6
6
|
<div className="grid max-w-2xl gap-3">
|
|
7
7
|
<Callout tone="accent" icon={<LightbulbIcon />} title="The takeaway">
|
|
8
|
-
Two of eleven
|
|
8
|
+
Two of eleven pricing tests raised revenue; <strong>none</strong> held up in both regions.
|
|
9
9
|
</Callout>
|
|
10
|
-
<Callout icon={<InfoIcon />} title="How the
|
|
11
|
-
|
|
10
|
+
<Callout icon={<InfoIcon />} title="How the tests were run">
|
|
11
|
+
Four weeks each on a random tenth of new visitors, with refunds and payment fees taken off.
|
|
12
12
|
</Callout>
|
|
13
13
|
<Callout tone="warning" icon={<TriangleAlertIcon />} title="Do not use the combined result">
|
|
14
|
-
|
|
14
|
+
It counted orders placed before the test began, so its revenue claims are withdrawn.
|
|
15
15
|
</Callout>
|
|
16
16
|
<div className="grid gap-3 sm:grid-cols-2">
|
|
17
|
-
<Callout tone="positive" icon={<TrendingUpIcon />} title="Best
|
|
18
|
-
|
|
17
|
+
<Callout tone="positive" icon={<TrendingUpIcon />} title="Best test">
|
|
18
|
+
Annual plan shown first: <strong className="whitespace-nowrap">+₹10,616</strong> a week.
|
|
19
19
|
</Callout>
|
|
20
|
-
<Callout tone="negative" icon={<TrendingDownIcon />} title="Worst
|
|
21
|
-
|
|
20
|
+
<Callout tone="negative" icon={<TrendingDownIcon />} title="Worst test">
|
|
21
|
+
Free delivery only above ₹999: <strong className="whitespace-nowrap">−₹70,679</strong> a week.
|
|
22
22
|
</Callout>
|
|
23
23
|
</div>
|
|
24
|
-
<Quote source="
|
|
25
|
-
|
|
24
|
+
<Quote source="The hosting provider's incident report, 21 Oct 2026">
|
|
25
|
+
Requests to the Mumbai region failed for 42 minutes after a configuration change, which has been rolled back.
|
|
26
26
|
</Quote>
|
|
27
|
-
<
|
|
28
|
-
<AlertTitle>
|
|
29
|
-
<AlertDescription>
|
|
30
|
-
</
|
|
27
|
+
<StatusAlert tone="warning">
|
|
28
|
+
<AlertTitle>Order history is incomplete</AlertTitle>
|
|
29
|
+
<AlertDescription>The old shop's export starts in April 2024; earlier orders are missing.</AlertDescription>
|
|
30
|
+
</StatusAlert>
|
|
31
31
|
</div>
|
|
32
32
|
);
|
|
33
33
|
}
|
package/agents/examples/card.tsx
CHANGED
|
@@ -16,8 +16,8 @@ export default function CardExample() {
|
|
|
16
16
|
return (
|
|
17
17
|
<Card>
|
|
18
18
|
<CardHeader>
|
|
19
|
-
<CardTitle>
|
|
20
|
-
<CardDescription>Across all
|
|
19
|
+
<CardTitle>Revenue this quarter</CardTitle>
|
|
20
|
+
<CardDescription>Across all stores</CardDescription>
|
|
21
21
|
<CardAction>
|
|
22
22
|
<Button variant="outline" size="sm">
|
|
23
23
|
<DownloadIcon />
|
|
@@ -29,7 +29,7 @@ export default function CardExample() {
|
|
|
29
29
|
<p className="text-3xl font-semibold">{money(4512300)}</p>
|
|
30
30
|
</CardContent>
|
|
31
31
|
<CardFooter>
|
|
32
|
-
<p className="text-muted-foreground">Updated
|
|
32
|
+
<p className="text-muted-foreground">Updated every night at midnight</p>
|
|
33
33
|
</CardFooter>
|
|
34
34
|
</Card>
|
|
35
35
|
);
|
|
@@ -17,33 +17,33 @@ import {
|
|
|
17
17
|
type DataTableColumnDef,
|
|
18
18
|
} from "@siyahi/ui";
|
|
19
19
|
|
|
20
|
-
interface
|
|
21
|
-
|
|
22
|
-
/**
|
|
20
|
+
interface Region {
|
|
21
|
+
region: string;
|
|
22
|
+
/** Revenue in January and in February, in rupees; made-up figures. */
|
|
23
23
|
january: number;
|
|
24
24
|
february: number;
|
|
25
25
|
change: number;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
|
|
28
|
+
const region = (name: string, january: number, february: number): Region => ({
|
|
29
|
+
region: name,
|
|
30
30
|
january,
|
|
31
31
|
february,
|
|
32
32
|
change: february / january - 1,
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
const regions: Region[] = [
|
|
36
|
+
region("West", 231900, 258000),
|
|
37
|
+
region("South", 248300, 262500),
|
|
38
|
+
region("Central", 161300, 166000),
|
|
39
|
+
region("East", 250400, 255600),
|
|
40
|
+
region("Northeast", 283100, 276000),
|
|
41
|
+
region("North", 241800, 224400),
|
|
42
42
|
];
|
|
43
43
|
|
|
44
44
|
// Every bar is a share of the column's largest move, and the column holds gains and losses, so the bars diverge.
|
|
45
|
-
const largestChange = Math.max(...
|
|
46
|
-
const diverging =
|
|
45
|
+
const largestChange = Math.max(...regions.map((r) => Math.abs(r.change)));
|
|
46
|
+
const diverging = regions.some((r) => r.change < 0) && regions.some((r) => r.change > 0);
|
|
47
47
|
|
|
48
48
|
function Money({ amount, muted = false }: { amount: number; muted?: boolean }) {
|
|
49
49
|
const text = useFormat().money(amount);
|
|
@@ -52,20 +52,20 @@ function Money({ amount, muted = false }: { amount: number; muted?: boolean }) {
|
|
|
52
52
|
|
|
53
53
|
const header = () => <DataTableSortHeader />;
|
|
54
54
|
|
|
55
|
-
const columns: DataTableColumnDef<
|
|
56
|
-
{ accessorKey: "
|
|
55
|
+
const columns: DataTableColumnDef<Region>[] = [
|
|
56
|
+
{ accessorKey: "region", header, size: 130, meta: { label: "Region", compact: true } },
|
|
57
57
|
{
|
|
58
58
|
accessorKey: "january",
|
|
59
59
|
header,
|
|
60
60
|
size: 130,
|
|
61
|
-
meta: { label: "
|
|
61
|
+
meta: { label: "January", variant: "number" },
|
|
62
62
|
cell: ({ row }) => <Money amount={row.original.january} muted />,
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
accessorKey: "february",
|
|
66
66
|
header,
|
|
67
67
|
size: 130,
|
|
68
|
-
meta: { label: "
|
|
68
|
+
meta: { label: "February", variant: "number", compact: true },
|
|
69
69
|
cell: ({ row }) => <Money amount={row.original.february} />,
|
|
70
70
|
},
|
|
71
71
|
{
|
|
@@ -81,11 +81,11 @@ export default function ChangeBarExample() {
|
|
|
81
81
|
return (
|
|
82
82
|
<Card>
|
|
83
83
|
<CardHeader>
|
|
84
|
-
<CardTitle>
|
|
85
|
-
<CardDescription>Each
|
|
84
|
+
<CardTitle>The West grew 11.3% in February, the North fell 7.2%</CardTitle>
|
|
85
|
+
<CardDescription>Each region's revenue in February against January</CardDescription>
|
|
86
86
|
</CardHeader>
|
|
87
87
|
<CardContent>
|
|
88
|
-
<DataTableRoot data={
|
|
88
|
+
<DataTableRoot data={regions} columns={columns}>
|
|
89
89
|
<DataTableToolbarSection>
|
|
90
90
|
<DataTableCompactColumnsToggle />
|
|
91
91
|
</DataTableToolbarSection>
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import { AreaChartCard, ToggleGroup, ToggleGroupItem, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
2
2
|
|
|
3
3
|
const data = [
|
|
4
|
-
{ month: "May",
|
|
5
|
-
{ month: "Jun",
|
|
6
|
-
{ month: "Jul",
|
|
7
|
-
{ month: "Aug",
|
|
8
|
-
{ month: "Sep",
|
|
9
|
-
{ month: "Oct",
|
|
4
|
+
{ month: "May", revenue: 3820000, target: 3600000 },
|
|
5
|
+
{ month: "Jun", revenue: 3950000, target: 3685000 },
|
|
6
|
+
{ month: "Jul", revenue: 4110000, target: 3770000 },
|
|
7
|
+
{ month: "Aug", revenue: 4020000, target: 3855000 },
|
|
8
|
+
{ month: "Sep", revenue: 4380000, target: 3940000 },
|
|
9
|
+
{ month: "Oct", revenue: 4512300, target: 4025000 },
|
|
10
10
|
];
|
|
11
11
|
|
|
12
12
|
// The title states the finding, not the measure: what the reader would say after looking.
|
|
13
|
-
// The first series fills; the
|
|
13
|
+
// The first series fills; the target draws as a line over it.
|
|
14
14
|
const series: ChartSeries<(typeof data)[number]> = [
|
|
15
|
-
{ key: "
|
|
16
|
-
{ key: "
|
|
15
|
+
{ key: "revenue", label: "Revenue", color: "var(--chart-1)" },
|
|
16
|
+
{ key: "target", label: "Target", color: "var(--chart-2)" },
|
|
17
17
|
];
|
|
18
18
|
|
|
19
19
|
export default function ChartAreaExample() {
|
|
20
20
|
const { money, moneyCompact } = useFormat();
|
|
21
21
|
return (
|
|
22
22
|
<AreaChartCard
|
|
23
|
-
title="₹4.9L ahead of
|
|
24
|
-
description="
|
|
23
|
+
title="October revenue ₹4.9L ahead of target"
|
|
24
|
+
description="Each month's revenue against its target"
|
|
25
25
|
action={
|
|
26
26
|
<ToggleGroup defaultValue={["6M"]} variant="outline" size="sm" aria-label="Range">
|
|
27
27
|
<ToggleGroupItem value="6M">6M</ToggleGroupItem>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BarChartCard, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
2
2
|
|
|
3
|
-
// Money into and out of
|
|
3
|
+
// Money into and out of a shop's bank account each month; out is negative. Made-up figures.
|
|
4
4
|
const data = [
|
|
5
5
|
{ month: "Jul", in: 84000, out: -52000 },
|
|
6
6
|
{ month: "Aug", in: 61000, out: -73000 },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BarChartCard, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// A new product line's operating result per financial year, a loss every year; made-up figures.
|
|
4
4
|
const data = [
|
|
5
5
|
{ fy: "FY23", net: -48000 },
|
|
6
6
|
{ fy: "FY24", net: -91000 },
|
|
@@ -9,14 +9,14 @@ const data = [
|
|
|
9
9
|
];
|
|
10
10
|
|
|
11
11
|
const series: ChartSeries<(typeof data)[number]> = [
|
|
12
|
-
{ key: "net", label: "
|
|
12
|
+
{ key: "net", label: "Operating result", color: "var(--positive)", negativeColor: "var(--negative)" },
|
|
13
13
|
];
|
|
14
14
|
|
|
15
15
|
export default function ChartBarLossesExample() {
|
|
16
16
|
const { money, moneyCompact } = useFormat();
|
|
17
17
|
return (
|
|
18
18
|
<BarChartCard
|
|
19
|
-
title="
|
|
19
|
+
title="Operating loss by financial year"
|
|
20
20
|
description="A loss every year, so every bar runs down from zero"
|
|
21
21
|
data={data}
|
|
22
22
|
xKey="fy"
|
|
@@ -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
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
2
|
import { BarChartCard, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
3
3
|
|
|
4
|
-
// Net
|
|
4
|
+
// Net profit per financial year (April to March); made-up figures.
|
|
5
5
|
const data = [
|
|
6
6
|
{ fy: "FY22", net: 142000 },
|
|
7
7
|
{ fy: "FY23", net: 186000 },
|
|
@@ -12,19 +12,19 @@ const data = [
|
|
|
12
12
|
|
|
13
13
|
// A gain and a loss take the meaning colours; the arrow in each tick says the same without colour.
|
|
14
14
|
const series: ChartSeries<(typeof data)[number]> = [
|
|
15
|
-
{ key: "net", label: "Net
|
|
15
|
+
{ key: "net", label: "Net profit", color: "var(--positive)", negativeColor: "var(--negative)" },
|
|
16
16
|
];
|
|
17
17
|
|
|
18
18
|
export default function ChartBarYearsExample() {
|
|
19
19
|
const { money, moneyCompact } = useFormat();
|
|
20
20
|
// The page owns the pick, so it can narrow the rest of the page to that year.
|
|
21
21
|
const [year, setYear] = useState<string | null>(null);
|
|
22
|
-
const signed = (v: number) => `${v < 0 ? "
|
|
22
|
+
const signed = (v: number) => `${v < 0 ? "\u2212" : "+"}${moneyCompact(Math.abs(v))}`;
|
|
23
23
|
return (
|
|
24
24
|
<BarChartCard
|
|
25
|
-
title="
|
|
25
|
+
title="Profit by financial year"
|
|
26
26
|
description={
|
|
27
|
-
year ? `${year} picked; click it again for every year` : "April to March,
|
|
27
|
+
year ? `${year} picked; click it again for every year` : "April to March, before tax. Click a year to pick it."
|
|
28
28
|
}
|
|
29
29
|
data={data}
|
|
30
30
|
xKey="fy"
|