UsageChartTooltips.tsx112 lines · main
1import type { Payload, ValueType } from 'recharts/types/component/DefaultTooltipContent'
2import { cn } from 'ui'
3
4import { Attribute, COLOR_MAP } from './Usage.constants'
5
6export interface SingleAttributeTooltipContentProps {
7 name: string
8 unit: 'bytes' | 'percentage' | 'absolute' | 'hours' | 'gigabytes'
9 value: any
10 isAfterToday: boolean
11 tooltipFormatter?: (value: any) => any
12}
13
14export const SingleAttributeTooltipContent = ({
15 name,
16 unit,
17 value,
18 isAfterToday,
19 tooltipFormatter,
20}: SingleAttributeTooltipContentProps) => {
21 const formattedValue = unit === 'percentage' ? Number(value).toFixed(2) : Number(value)
22 return (
23 <>
24 <p className="text-xs text-foreground-light">{name}</p>
25 {isAfterToday ? (
26 <p className="text-foreground-light text-lg">No data yet</p>
27 ) : (
28 <p className="text-xl">
29 {tooltipFormatter !== undefined ? tooltipFormatter(formattedValue) : formattedValue}
30 </p>
31 )}
32 </>
33 )
34}
35
36export interface MultiAttributeTooltipContentProps {
37 attributes: Attribute[]
38 values: Payload<ValueType, string | number>[]
39 isAfterToday: boolean
40 tooltipFormatter?: (value: any) => any
41 unit: 'bytes' | 'percentage' | 'absolute' | 'hours' | 'gigabytes'
42}
43
44const AttributeContent = ({
45 attribute,
46 attributeMeta,
47 sumValue,
48 tooltipFormatter,
49 unit,
50}: {
51 attribute: Attribute
52 attributeMeta?: Payload<ValueType, string | number>
53 sumValue: number
54 tooltipFormatter?: (value: any) => any
55 unit: 'bytes' | 'percentage' | 'absolute' | 'hours' | 'gigabytes'
56}) => {
57 const attrValue = Number(attributeMeta?.value ?? 0)
58 const percentageContribution = ((attrValue / sumValue) * 100).toFixed(1)
59
60 return (
61 <div key={attribute.name} className="flex items-center justify-between">
62 <div className="flex items-center space-x-2 w-[175px]">
63 <div className={cn('w-3 h-3 rounded-full border', COLOR_MAP[attribute.color].marker)} />
64 <p className="text-xs prose">
65 {attribute.name} ({percentageContribution}%):{' '}
66 </p>
67 </div>
68 <p className="text-xs tabular-nums">
69 {tooltipFormatter !== undefined
70 ? tooltipFormatter(attrValue)
71 : `${attrValue}${unit === 'hours' ? ' H' : ''}`}
72 </p>
73 </div>
74 )
75}
76
77export const MultiAttributeTooltipContent = ({
78 attributes,
79 values,
80 isAfterToday,
81 tooltipFormatter,
82 unit,
83}: MultiAttributeTooltipContentProps) => {
84 const sumValue = values.reduce((a, b) => a + Number(b.value), 0)
85 return (
86 <>
87 {isAfterToday ? (
88 <p className="text-foreground-light text-lg">No data yet</p>
89 ) : (
90 <div className="space-y-1 pb-1">
91 {attributes.flatMap((attr) => {
92 const attributeMeta = values.find((x) => x.dataKey === attr.key)
93
94 // Filter out empty attributes
95 if (Number(attributeMeta?.value ?? 0) === 0) return []
96
97 return (
98 <AttributeContent
99 key={attr.name}
100 attribute={attr}
101 attributeMeta={attributeMeta}
102 sumValue={sumValue}
103 tooltipFormatter={tooltipFormatter}
104 unit={unit}
105 />
106 )
107 })}
108 </div>
109 )}
110 </>
111 )
112}