Open History to see the last commit
1import { formatPercent } from "@t3tools/shared/usageFormat";
2import type { ReactNode } from "react";
3
4import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
5
6export interface ShareSegment {
7 readonly label: string;
8 readonly value: number;
9 readonly color: string;
10}
11
12export function UsageShareBar({
13 label,
14 segments,
15 format,
16 aside,
17}: {
18 readonly label: string;
19 readonly segments: readonly ShareSegment[];
20 readonly format: (value: number) => string;
21 readonly aside?: ReactNode;
22}) {
23 const visible = segments.filter((segment) => segment.value > 0);
24 const total = visible.reduce((sum, segment) => sum + segment.value, 0);
25 if (total <= 0) return null;
26
27 return (
28 <div className="flex min-w-0 flex-col gap-2.5">
29 <div className="flex items-baseline justify-between gap-3">
30 <h3 className="text-meta text-foreground">{label}</h3>
31 {aside}
32 </div>
33 <div
34 role="img"
35 aria-label={`${label}: ${visible.map((segment) => `${segment.label} ${format(segment.value)}`).join(", ")}`}
36 className="flex h-2 gap-0.5"
37 >
38 {visible.map((segment) => (
39 <Tooltip key={segment.label}>
40 <TooltipTrigger
41 render={
42 <div
43 className="h-full min-w-1 rounded-xs first:rounded-l-full last:rounded-r-full"
44 style={{ flex: `${segment.value} 1 0`, backgroundColor: segment.color }}
45 />
46 }
47 />
48 <TooltipPopup>
49 <div className="flex flex-col gap-0.5">
50 <span>{segment.label}</span>
51 <span>{format(segment.value)}</span>
52 <span>{formatPercent(segment.value / total)}</span>
53 </div>
54 </TooltipPopup>
55 </Tooltip>
56 ))}
57 </div>
58 <div className="flex flex-wrap gap-x-4 gap-y-1 text-caption">
59 {visible.map((segment) => (
60 <span key={segment.label} className="flex items-center gap-1.5">
61 <span
62 aria-hidden
63 className="size-2 rounded-xs"
64 style={{ backgroundColor: segment.color }}
65 />
66 <span className="text-muted-foreground">{segment.label}</span>
67 <span className="text-foreground tabular-nums">{format(segment.value)}</span>
68 </span>
69 ))}
70 </div>
71 </div>
72 );
73}