From d4e4ca819c0e373af4b5cae5d2d39d6162f651a6 Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Sat, 21 Mar 2026 22:59:41 +0100 Subject: [PATCH] fix: add numeric Y-axis to bar chart view --- components/dashboard/Chart.tsx | 9 ++++++- components/ui/bar-chart.tsx | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/components/dashboard/Chart.tsx b/components/dashboard/Chart.tsx index e78c424..f24b5ce 100644 --- a/components/dashboard/Chart.tsx +++ b/components/dashboard/Chart.tsx @@ -3,7 +3,7 @@ import { useState, useMemo, useRef, useCallback, useEffect } from 'react' import { useTheme } from '@ciphera-net/ui' import { AreaChart as VisxAreaChart, Area as VisxArea, Grid as VisxGrid, XAxis as VisxXAxis, YAxis as VisxYAxis, ChartTooltip as VisxChartTooltip, type TooltipRow } from '@/components/ui/area-chart' -import { BarChart as VisxBarChart, Bar as VisxBar, Grid as VisxBarGrid, BarXAxis as VisxBarXAxis, ChartTooltip as VisxBarChartTooltip } from '@/components/ui/bar-chart' +import { BarChart as VisxBarChart, Bar as VisxBar, Grid as VisxBarGrid, BarXAxis as VisxBarXAxis, BarValueAxis as VisxBarYAxis, ChartTooltip as VisxBarChartTooltip } from '@/components/ui/bar-chart' import { ChartLine, ChartBar } from '@phosphor-icons/react' import { Card, CardContent, CardHeader } from '@/components/ui/card' import { formatNumber, formatDuration, formatUpdatedAgo, DatePicker } from '@ciphera-net/ui' @@ -492,6 +492,13 @@ export default function Chart({ lineCap="round" /> + { + const config = METRIC_CONFIGS.find((m) => m.key === metric) + return config ? config.format(v) : v.toString() + }} + /> { const config = METRIC_CONFIGS.find((m) => m.key === metric) diff --git a/components/ui/bar-chart.tsx b/components/ui/bar-chart.tsx index 6740881..160952c 100644 --- a/components/ui/bar-chart.tsx +++ b/components/ui/bar-chart.tsx @@ -583,6 +583,50 @@ export function BarXAxis({ tickerHalfWidth = 50, showAllLabels = false, maxLabel BarXAxis.displayName = "BarXAxis"; +// ─── BarValueAxis (numeric Y-axis for vertical bar charts) ─────────────── + +export interface BarValueAxisProps { + numTicks?: number; + formatValue?: (value: number) => string; +} + +export function BarValueAxis({ numTicks = 5, formatValue }: BarValueAxisProps) { + const { yScale, margin, containerRef } = useChart(); + const [container, setContainer] = useState(null); + + useEffect(() => { setContainer(containerRef.current); }, [containerRef]); + + const ticks = useMemo(() => { + const domain = yScale.domain() as [number, number]; + const min = domain[0]; + const max = domain[1]; + const step = (max - min) / (numTicks - 1); + return Array.from({ length: numTicks }, (_, i) => { + const value = min + step * i; + return { + value, + y: (yScale(value) ?? 0) + margin.top, + label: formatValue ? formatValue(value) : value >= 1000 ? `${(value / 1000).toFixed(value % 1000 === 0 ? 0 : 1)}k` : Math.round(value).toLocaleString(), + }; + }); + }, [yScale, margin.top, numTicks, formatValue]); + + if (!container) return null; + + return createPortal( +
+ {ticks.map((tick) => ( +
+ {tick.label} +
+ ))} +
, + container + ); +} + +BarValueAxis.displayName = "BarValueAxis"; + // ─── Bar ───────────────────────────────────────────────────────────────────── export interface BarProps {