Files
stats/apps/start/src/components/charts/chart-tooltip.tsx
Carl-Gerhard Lindesvärd 790801b728 feat: revenue tracking
* wip

* wip

* wip

* wip

* show revenue better on overview

* align realtime and overview counters

* update revenue docs

* always return device id

* add project settings, improve projects charts,

* fix: comments

* fixes

* fix migration

* ignore sql files

* fix comments
2025-11-19 14:27:34 +01:00

96 lines
2.3 KiB
TypeScript

import { cn } from '@/utils/cn';
import { createContext, useContext as useBaseContext } from 'react';
import { Tooltip as RechartsTooltip, type TooltipProps } from 'recharts';
export const ChartTooltipContainer = ({
children,
}: { children: React.ReactNode }) => {
return (
<div className="min-w-[180px] col gap-2 rounded-xl border bg-background/80 p-3 shadow-xl backdrop-blur-sm">
{children}
</div>
);
};
export const ChartTooltipHeader = ({
children,
}: { children: React.ReactNode }) => {
return <div className="flex justify-between gap-8">{children}</div>;
};
export const ChartTooltipItem = ({
children,
color,
className,
innerClassName,
}: {
children: React.ReactNode;
color: string;
className?: string;
innerClassName?: string;
}) => {
return (
<div className={cn('flex gap-2', className)}>
<div className="w-[3px] rounded-full" style={{ background: color }} />
<div className={cn('col flex-1 gap-1', innerClassName)}>{children}</div>
</div>
);
};
export function createChartTooltip<
PropsFromTooltip,
PropsFromContext extends Record<string, unknown>,
>(
Tooltip: React.ComponentType<
{
context: PropsFromContext;
data: PropsFromTooltip[];
} & TooltipProps<number, string>
>,
) {
const context = createContext<PropsFromContext | null>(null);
const useContext = () => {
const value = useBaseContext(context);
if (!value) {
throw new Error('ChartTooltip context not found');
}
return value;
};
const InnerTooltip = (tooltip: TooltipProps<number, string>) => {
const context = useContext();
const data = tooltip.payload?.map((p) => p.payload) ?? [];
if (!data || !tooltip.active) {
return null;
}
return (
<ChartTooltipContainer>
<Tooltip data={data} context={context} {...tooltip} />
</ChartTooltipContainer>
);
};
return {
TooltipProvider: ({
children,
...value
}: {
children: React.ReactNode;
} & PropsFromContext) => {
return (
<context.Provider value={value as unknown as PropsFromContext}>
{children}
</context.Provider>
);
},
Tooltip: (props: TooltipProps<number, string>) => {
return (
<RechartsTooltip {...props} content={<InnerTooltip {...props} />} />
);
},
};
}