feat: add ThemedChart wrapper component

This commit is contained in:
hsiegeln
2026-04-12 19:34:21 +02:00
parent ce93ba456c
commit 99ff461d4d
2 changed files with 112 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
import { describe, it, expect } from 'vitest'
import { render } from '@testing-library/react'
import { ThemedChart } from './ThemedChart'
import { Line } from 'recharts'
// Recharts uses ResizeObserver internally
class ResizeObserverMock {
observe() {}
unobserve() {}
disconnect() {}
}
globalThis.ResizeObserver = ResizeObserverMock as any
describe('ThemedChart', () => {
it('renders nothing when data is empty', () => {
const { container } = render(
<ThemedChart data={[]}>
<Line dataKey="value" />
</ThemedChart>,
)
expect(container.innerHTML).toBe('')
})
it('renders a chart container when data is provided', () => {
const data = [
{ time: '10:00', value: 10 },
{ time: '10:01', value: 20 },
]
const { container } = render(
<ThemedChart data={data} height={160}>
<Line dataKey="value" />
</ThemedChart>,
)
expect(container.querySelector('.recharts-responsive-container')).toBeTruthy()
})
it('applies custom className', () => {
const data = [{ time: '10:00', value: 5 }]
const { container } = render(
<ThemedChart data={data} className="my-chart">
<Line dataKey="value" />
</ThemedChart>,
)
expect(container.querySelector('.my-chart')).toBeTruthy()
})
})

View File

@@ -0,0 +1,66 @@
import {
ResponsiveContainer,
ComposedChart,
CartesianGrid,
XAxis,
YAxis,
Tooltip,
} from 'recharts'
import { rechartsTheme } from '../../utils/rechartsTheme'
import { ChartTooltip } from './ChartTooltip'
interface ThemedChartProps {
data: Record<string, any>[]
height?: number
xDataKey?: string
xType?: 'number' | 'category'
xTickFormatter?: (value: any) => string
yTickFormatter?: (value: any) => string
yLabel?: string
children: React.ReactNode
className?: string
}
export function ThemedChart({
data,
height = 200,
xDataKey = 'time',
xType = 'category',
xTickFormatter,
yTickFormatter,
yLabel,
children,
className,
}: ThemedChartProps) {
if (!data.length) {
return null
}
return (
<div className={className} style={{ width: '100%', height }}>
<ResponsiveContainer width="100%" height="100%">
<ComposedChart data={data} margin={{ top: 4, right: 8, bottom: 0, left: 0 }}>
<CartesianGrid {...rechartsTheme.cartesianGrid} />
<XAxis
dataKey={xDataKey}
type={xType}
{...rechartsTheme.xAxis}
tickFormatter={xTickFormatter}
/>
<YAxis
{...rechartsTheme.yAxis}
tickFormatter={yTickFormatter}
label={yLabel ? {
value: yLabel,
angle: -90,
position: 'insideLeft',
style: { fontSize: 11, fill: 'var(--text-muted)' },
} : undefined}
/>
<Tooltip content={<ChartTooltip />} cursor={rechartsTheme.tooltip.cursor} />
{children}
</ComposedChart>
</ResponsiveContainer>
</div>
)
}