feat: add ChartTooltip component for ThemedChart

This commit is contained in:
hsiegeln
2026-04-12 19:33:45 +02:00
parent 3fc5fb8267
commit ce93ba456c
2 changed files with 88 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
.tooltip {
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
box-shadow: var(--shadow-md);
padding: 6px 10px;
font-size: 12px;
}
.time {
font-family: var(--font-mono);
font-size: 10px;
color: var(--text-muted);
margin-bottom: 4px;
padding-bottom: 3px;
border-bottom: 1px solid var(--border-subtle);
}
.row {
display: flex;
align-items: center;
gap: 5px;
margin-bottom: 2px;
}
.row:last-child {
margin-bottom: 0;
}
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
flex-shrink: 0;
}
.label {
color: var(--text-muted);
font-size: 11px;
}
.value {
font-family: var(--font-mono);
font-weight: 600;
font-size: 11px;
color: var(--text-primary);
}

View File

@@ -0,0 +1,41 @@
import type { TooltipProps } from 'recharts'
import styles from './ChartTooltip.module.css'
function formatValue(val: number): string {
if (val >= 1_000_000) return `${(val / 1_000_000).toFixed(1)}M`
if (val >= 1000) return `${(val / 1000).toFixed(1)}k`
if (Number.isInteger(val)) return String(val)
return val.toFixed(1)
}
function formatTimestamp(val: unknown): string | null {
if (val == null) return null
const str = String(val)
const ms = typeof val === 'number' && val > 1e12 ? val
: typeof val === 'number' && val > 1e9 ? val * 1000
: Date.parse(str)
if (isNaN(ms)) return str
return new Date(ms).toLocaleString([], {
month: 'short', day: 'numeric',
hour: '2-digit', minute: '2-digit', second: '2-digit',
})
}
export function ChartTooltip({ active, payload, label }: TooltipProps<number, string>) {
if (!active || !payload?.length) return null
const timeLabel = formatTimestamp(label)
return (
<div className={styles.tooltip}>
{timeLabel && <div className={styles.time}>{timeLabel}</div>}
{payload.map((entry) => (
<div key={entry.dataKey as string} className={styles.row}>
<span className={styles.dot} style={{ background: entry.color }} />
<span className={styles.label}>{entry.name}:</span>
<span className={styles.value}>{formatValue(entry.value as number)}</span>
</div>
))}
</div>
)
}