Chart Frame
Reusable chart chrome: useSize (ResizeObserver real-pixel measure), ChartPanel (titled, measured plot area), ChartEmpty (an honest empty state - never a blank axis pretending to have data). Generic.
Reference implementation: this source keeps imports to modules from its home codebase. Read it for the technique, adapt the imports to yours; it is not drop-in compile-ready, on purpose.
"use client";
import { useEffect, useRef, useState, type ReactNode } from "react";
import s from "../compare.module.css";
/** measure a container so charts render at real pixels (no viewBox distortion) */
export function useSize<T extends HTMLElement>() {
const ref = useRef<T>(null);
const [size, setSize] = useState({ w: 0, h: 0 });
useEffect(() => {
const el = ref.current;
if (!el) return;
const ro = new ResizeObserver(([e]) => setSize({ w: Math.round(e.contentRect.width), h: Math.round(e.contentRect.height) }));
ro.observe(el);
return () => ro.disconnect();
}, []);
return [ref, size] as const;
}
/** honest empty state for any chart — never a blank axis pretending to have data */
export function ChartEmpty({ title, msg, tier }: { title: string; msg: string; tier?: "telemetry" | "derived" }) {
return (
<div className={s.panelWell}>
<div className={s.panelTop}>
<span className="kicker">{title}</span>
{tier && <span className="tier" data-tier={tier}>{tier === "telemetry" ? "FEED" : "DERIVED"}</span>}
</div>
<div className={s.chartEmpty}><p>{msg}</p></div>
</div>
);
}
/** panel chrome shared by the SVG charts: title + tier chip + a measured plot area */
export function ChartPanel({
title,
tier,
note,
children,
}: {
title: string;
tier: "telemetry" | "derived";
note?: string;
children: (w: number, h: number) => ReactNode;
}) {
const [ref, { w, h }] = useSize<HTMLDivElement>();
return (
<div className={s.panelWell}>
<div className={s.panelTop}>
<span className="kicker">{title}</span>
{note && <span className={`${s.panelNote} tag`}>{note}</span>}
<span className="tier" data-tier={tier}>{tier === "telemetry" ? "FEED" : "DERIVED"}</span>
</div>
<div className={s.chartArea} ref={ref}>
{w > 0 && h > 0 ? children(w, h) : null}
</div>
</div>
);
}