Merge pull request #4259 from yancat160/feat/persist-hidden-events-across-range

fix: keep hidden events hidden across date-range changes
This commit is contained in:
Mike Cao
2026-05-15 00:15:40 -04:00
committed by GitHub
2 changed files with 41 additions and 1 deletions
+29 -1
View File
@@ -18,6 +18,8 @@ export interface ChartProps extends BoxProps {
updateMode?: UpdateMode;
animationDuration?: number;
onTooltip?: (model: any) => void;
hiddenLabels?: Set<string>;
onLegendClick?: (label: string, willBeHidden: boolean) => void;
}
export function Chart({
@@ -27,6 +29,8 @@ export function Chart({
updateMode,
onTooltip,
chartOptions,
hiddenLabels,
onLegendClick,
...props
}: ChartProps) {
const canvas = useRef(null);
@@ -61,6 +65,15 @@ export function Chart({
}, [chartOptions]);
const handleLegendClick = (item: LegendItem) => {
if (onLegendClick && type === 'bar') {
// Controlled mode: caller owns the hidden state. We report the click
// and let the parent push a new hiddenLabels set on the next render.
const { datasetIndex } = item;
const ds = chart.current.data.datasets[datasetIndex];
onLegendClick(ds.label, !hiddenLabels?.has(ds.label));
return;
}
if (type === 'bar') {
const { datasetIndex } = item;
const meta = chart.current.getDatasetMeta(datasetIndex);
@@ -111,13 +124,28 @@ export function Chart({
});
}
// Re-apply caller-driven hidden flags after focusLabel handling so a
// dataset stays hidden across data changes (e.g. date-range switches)
// even though Chart.js regenerates dataset meta on every replace.
if (hiddenLabels) {
chart.current.data.datasets.forEach((ds: { hidden: boolean; label: any }) => {
if (hiddenLabels.has(ds.label)) {
ds.hidden = true;
} else if (!chartData.focusLabel) {
// Explicitly reset so un-hiding a label is always reflected,
// regardless of whether the focusLabel pass ran above.
ds.hidden = false;
}
});
}
chart.current.options = options;
chart.current.update(updateMode);
setLegendItems(chart.current.legend.legendItems);
}
}, [chartData, options, updateMode]);
}, [chartData, options, updateMode, hiddenLabels]);
return (
<Column gap="6">
+12
View File
@@ -27,6 +27,16 @@ export function EventsChart({ websiteId, focusLabel, limit }: EventsChartProps)
const { locale, dateLocale } = useLocale();
const { data, isLoading, error } = useWebsiteEventsSeriesQuery(websiteId, { limit });
const [label, setLabel] = useState<string>(focusLabel);
const [hiddenLabels, setHiddenLabels] = useState<Set<string>>(() => new Set());
const handleLegendClick = useCallback((legendLabel: string, willBeHidden: boolean) => {
setHiddenLabels(prev => {
const next = new Set(prev);
if (willBeHidden) next.add(legendLabel);
else next.delete(legendLabel);
return next;
});
}, []);
const chartData: any = useMemo(() => {
if (!data) return;
@@ -115,6 +125,8 @@ export function EventsChart({ websiteId, focusLabel, limit }: EventsChartProps)
stacked={true}
renderXLabel={renderXLabel}
height="400px"
hiddenLabels={hiddenLabels}
onLegendClick={handleLegendClick}
/>
)}
</LoadingPanel>