From 31328d5a3b33c8b7d45a76bbc107a724bc618007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 27 Mar 2026 08:47:07 -0400 Subject: [PATCH] feat(08-01): create ChartCard wrapper and ChartTooltip components - ChartCard: shared chart card with title, period badge, empty state, role="img" accessibility - ChartTooltip: custom Recharts tooltip with design system tokens, color dots, mono font - Both use CSS custom properties for automatic dark mode support - TypeScript compiles cleanly with Recharts TooltipContentProps type Co-Authored-By: Claude Opus 4.6 (1M context) --- .../components/dashboard/charts/ChartCard.tsx | 54 ++++++++++++++++++ .../dashboard/charts/ChartTooltip.tsx | 57 +++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 src/renderer/components/dashboard/charts/ChartCard.tsx create mode 100644 src/renderer/components/dashboard/charts/ChartTooltip.tsx diff --git a/src/renderer/components/dashboard/charts/ChartCard.tsx b/src/renderer/components/dashboard/charts/ChartCard.tsx new file mode 100644 index 00000000..e99f5166 --- /dev/null +++ b/src/renderer/components/dashboard/charts/ChartCard.tsx @@ -0,0 +1,54 @@ +import { ChartLine } from "@phosphor-icons/react"; + +interface ChartCardProps { + title: string; + period?: string; + isEmpty?: boolean; + emptyHeading?: string; + emptyBody?: string; + ariaLabel?: string; + children: React.ReactNode; +} + +export function ChartCard({ + title, + period = "14d", + isEmpty = false, + emptyHeading = "No activity yet", + emptyBody = "Charts will appear once your company starts running tasks.", + ariaLabel, + children, +}: ChartCardProps) { + return ( +
+
+ + {title} + + + {period} + +
+ {isEmpty ? ( +
+ + + {emptyHeading} + + + {emptyBody} + +
+ ) : ( +
{children}
+ )} +
+ ); +} diff --git a/src/renderer/components/dashboard/charts/ChartTooltip.tsx b/src/renderer/components/dashboard/charts/ChartTooltip.tsx new file mode 100644 index 00000000..0a0a538c --- /dev/null +++ b/src/renderer/components/dashboard/charts/ChartTooltip.tsx @@ -0,0 +1,57 @@ +import type { TooltipContentProps } from "recharts"; + +interface ChartTooltipExtraProps { + valuePrefix?: string; + valueSuffix?: string; +} + +type Props = Partial> & ChartTooltipExtraProps; + +export function ChartTooltip({ + active, + payload, + label, + valuePrefix = "", + valueSuffix = "", +}: Props) { + if (!active || !payload?.length) return null; + + const dateStr = + typeof label === "string" + ? new Date(label + "T00:00:00").toLocaleDateString("en-US", { + month: "short", + day: "numeric", + year: "numeric", + }) + : String(label); + + return ( +
+
{dateStr}
+ {payload.map((entry, i) => ( +
+ + + {valuePrefix} + {typeof entry.value === "number" + ? entry.value.toLocaleString() + : entry.value} + {valueSuffix} + +
+ ))} +
+ ); +}