Keep the theme redraw from wiping a chart's x scale
Reaching Home from another page builds its charts in the same commit their theme effect first fires in, with the readings already cached. uPlot ranges its scales in a microtask, so `redraw()` re-set the x scale from the chart's own — still empty — bounds before that ran, and the pending range taken from the data was lost: axes without ticks, no lines, and no way back but the range control, which rebuilds the chart. Redrawing without the paths is all a colour swap needs and leaves the scales alone. The cards also carried "Nothing has run yet." while the first readings were still on their way; they now carry the skeleton the rest of Home uses. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKL7sUgNWhukDEz95vSMQv
This commit is contained in:
@@ -4,6 +4,7 @@ import "uplot/dist/uPlot.min.css"
|
||||
|
||||
import type { HistoryPoint } from "@/client"
|
||||
import { useTheme } from "@/components/theme-provider"
|
||||
import { Skeleton } from "@/components/ui/skeleton"
|
||||
import { si } from "@/lib/utils"
|
||||
|
||||
/**
|
||||
@@ -74,6 +75,7 @@ export function UplotChart({
|
||||
labels,
|
||||
plots,
|
||||
empty = "Nothing has come through yet.",
|
||||
pending = false,
|
||||
unit,
|
||||
yRange,
|
||||
yLabel,
|
||||
@@ -85,6 +87,9 @@ export function UplotChart({
|
||||
/** The points of each series, in the same order as `labels`. */
|
||||
plots: HistoryPoint[][]
|
||||
empty?: string
|
||||
/** No readings yet because none have arrived: a chart with nothing in it
|
||||
* says "nothing has run", which is a different thing to say. */
|
||||
pending?: boolean
|
||||
/** Written after every reading, on the axis and in the legend. */
|
||||
unit?: string
|
||||
/** A y axis fixed to these bounds; unset lets it follow the data. */
|
||||
@@ -240,10 +245,16 @@ export function UplotChart({
|
||||
chart.current.setData(table(plots))
|
||||
}, [points, key])
|
||||
|
||||
// The canvas cannot follow a CSS variable, so a theme swap is a redraw.
|
||||
// The canvas cannot follow a CSS variable, so a theme swap is a redraw. The
|
||||
// paths are geometry and stay as they are — and leaving them alone is what
|
||||
// keeps this safe on the mount it also fires on: a full redraw re-sets the x
|
||||
// scale from the chart's own bounds, which are still empty when the chart was
|
||||
// built in this same commit (uPlot ranges its scales in a microtask). That
|
||||
// overwrites the range it was about to take from the data, and the chart is
|
||||
// left with no x axis and no lines until something sets its data again.
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: the theme is the signal, not something the effect reads.
|
||||
useEffect(() => {
|
||||
chart.current?.redraw()
|
||||
chart.current?.redraw(false)
|
||||
}, [resolvedTheme])
|
||||
|
||||
return (
|
||||
@@ -251,9 +262,13 @@ export function UplotChart({
|
||||
<div className="relative min-h-0 flex-1">
|
||||
<div ref={host} className="absolute inset-0" />
|
||||
{points === 0 ? (
|
||||
<p className="absolute inset-0 flex items-center justify-center text-sm text-muted-foreground">
|
||||
{empty}
|
||||
</p>
|
||||
pending ? (
|
||||
<Skeleton className="absolute inset-0" />
|
||||
) : (
|
||||
<p className="absolute inset-0 flex items-center justify-center text-sm text-muted-foreground">
|
||||
{empty}
|
||||
</p>
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
{/* Kept at the legend's resting height, so the plot does not resize
|
||||
|
||||
Reference in New Issue
Block a user