Use a distinct color palette for Frames / Detections graphs (#2)

The CPU and Frames / Detections graphs on the system metrics page both
rendered through CameraLineGraph with a single shared palette, making
the two graphs hard to tell apart at a glance.

Add an optional `colors` prop to CameraLineGraph (defaulting to the
existing palette so CPU graphs are unchanged) and give the Frames /
Detections graphs their own green/orange/cyan palette. The colors are
routed through both the chart lines and the legend dots so they stay
in sync.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
leccelecce
2026-06-25 22:42:50 +01:00
co-authored by Claude Opus 4.8
parent ec3fb00494
commit 7739a330d8
2 changed files with 14 additions and 4 deletions
+8 -3
View File
@@ -11,6 +11,9 @@ import useSWR from "swr";
import { useTimeFormat } from "@/hooks/use-date-utils"; import { useTimeFormat } from "@/hooks/use-date-utils";
const GRAPH_COLORS = ["#5C7CFA", "#ED5CFA", "#FAD75C"]; const GRAPH_COLORS = ["#5C7CFA", "#ED5CFA", "#FAD75C"];
// Distinct palette so the Frames / Detections graphs are easy to tell apart
// from the CPU graphs at a glance.
export const FPS_GRAPH_COLORS = ["#2DD4BF", "#818CFF", "#D17B88"];
type CameraLineGraphProps = { type CameraLineGraphProps = {
graphId: string; graphId: string;
@@ -19,6 +22,7 @@ type CameraLineGraphProps = {
updateTimes: number[]; updateTimes: number[];
data: ApexAxisChartSeries; data: ApexAxisChartSeries;
isActive?: boolean; isActive?: boolean;
colors?: string[];
}; };
export function CameraLineGraph({ export function CameraLineGraph({
graphId, graphId,
@@ -27,6 +31,7 @@ export function CameraLineGraph({
updateTimes, updateTimes,
data, data,
isActive = true, isActive = true,
colors = GRAPH_COLORS,
}: CameraLineGraphProps) { }: CameraLineGraphProps) {
const { t } = useTranslation(["views/system", "common"]); const { t } = useTranslation(["views/system", "common"]);
const { data: config } = useSWR<FrigateConfig>("config", { const { data: config } = useSWR<FrigateConfig>("config", {
@@ -91,7 +96,7 @@ export function CameraLineGraph({
enabled: false, enabled: false,
}, },
}, },
colors: GRAPH_COLORS, colors,
grid: { grid: {
show: false, show: false,
}, },
@@ -138,7 +143,7 @@ export function CameraLineGraph({
min: 0, min: 0,
}, },
} as ApexCharts.ApexOptions; } as ApexCharts.ApexOptions;
}, [graphId, systemTheme, theme, formatTime]); }, [graphId, colors, systemTheme, theme, formatTime]);
useEffect(() => { useEffect(() => {
ApexCharts.exec(graphId, "updateOptions", options, true, true); ApexCharts.exec(graphId, "updateOptions", options, true, true);
@@ -162,7 +167,7 @@ export function CameraLineGraph({
<div key={label} className="flex items-center gap-1"> <div key={label} className="flex items-center gap-1">
<MdCircle <MdCircle
className="size-2" className="size-2"
style={{ color: GRAPH_COLORS[labelIdx] }} style={{ color: colors[labelIdx] }}
/> />
<div className="text-xs text-secondary-foreground"> <div className="text-xs text-secondary-foreground">
{t("cameras.label." + label)} {t("cameras.label." + label)}
+6 -1
View File
@@ -1,5 +1,8 @@
import { useFrigateStats } from "@/api/ws"; import { useFrigateStats } from "@/api/ws";
import { CameraLineGraph } from "@/components/graph/LineGraph"; import {
CameraLineGraph,
FPS_GRAPH_COLORS,
} from "@/components/graph/LineGraph";
import CameraInfoDialog from "@/components/overlay/CameraInfoDialog"; import CameraInfoDialog from "@/components/overlay/CameraInfoDialog";
import { ConnectionQualityIndicator } from "@/components/camera/ConnectionQualityIndicator"; import { ConnectionQualityIndicator } from "@/components/camera/ConnectionQualityIndicator";
import { EmptyCard } from "@/components/card/EmptyCard"; import { EmptyCard } from "@/components/card/EmptyCard";
@@ -308,6 +311,7 @@ export default function CameraMetrics({
updateTimes={updateTimes} updateTimes={updateTimes}
data={overallFpsSeries} data={overallFpsSeries}
isActive={isActive} isActive={isActive}
colors={FPS_GRAPH_COLORS}
/> />
</div> </div>
) : ( ) : (
@@ -411,6 +415,7 @@ export default function CameraMetrics({
cameraFpsSeries[camera.name] || {}, cameraFpsSeries[camera.name] || {},
)} )}
isActive={isActive} isActive={isActive}
colors={FPS_GRAPH_COLORS}
/> />
</div> </div>
) : ( ) : (