Draw charts from one categorical palette, --chart-1…8
The one-hue ramp told lines apart by lightness alone. --chart-1 is now --primary and slots 2-8 are distinct hues (orange, violet, green, orchid, ochre, teal, magenta) that clear 3:1 on --card and stay apart under protanopia and deuteranopia; red and sage are left out as the status colours. A chart takes the slots in order instead of spreading a ramp, and a dashboard's own palette continues after its primary and listed colours with slots 2-8 rather than tints of its scheme. Line charts stay at five series. Tokens mirror index's, as design-check requires. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
This commit is contained in:
@@ -15,52 +15,31 @@ import { si } from "@/lib/utils"
|
||||
/**
|
||||
* How many lines one chart carries.
|
||||
*
|
||||
* The bound is the palette's: `--chart-1…5` is one designed ramp, and a sixth
|
||||
* line would either repeat a step or invent a colour outside the system.
|
||||
* Past five a legend is a puzzle, and five is as far as the palette keeps any
|
||||
* two lines apart for a colour-blind reader too, not only neighbouring ones.
|
||||
*/
|
||||
export const MAX_SERIES = 5
|
||||
|
||||
/**
|
||||
* The ramp's slots, as a palette names them.
|
||||
* The palette's slots, as a palette names them: `--chart-1…8`.
|
||||
*
|
||||
* The whole set one may draw from — five, for the same reason `MAX_SERIES` is
|
||||
* five, because they are the same five.
|
||||
* One categorical palette, taken in order. The first slot is the brand
|
||||
* primary and the rest are hues picked to stand apart from it and from each
|
||||
* other, so a line is told by its hue rather than by a step of lightness.
|
||||
*/
|
||||
export const CHART_SLOTS = Array.from({ length: MAX_SERIES }, (_, index) =>
|
||||
export const CHART_SLOTS = Array.from({ length: 8 }, (_, index) =>
|
||||
String(index + 1),
|
||||
)
|
||||
|
||||
/** No palette named; a chart left with this spreads itself. */
|
||||
/** No palette named; a chart left with this takes the slots in order. */
|
||||
export const NO_PALETTE: string[] = []
|
||||
|
||||
/**
|
||||
* What a chart of *n* lines draws with when no palette was named: the ramp
|
||||
* spread, rather than its first *n* steps.
|
||||
*
|
||||
* Three lines used to take slots 1, 2 and 3, which are adjacent steps of a
|
||||
* ramp that carries identity by lightness alone — at a 2px stroke they are
|
||||
* close to one picture. The ends and the middle are as far apart as five slots
|
||||
* allow, and the same reasoning gives every other count.
|
||||
*
|
||||
* This moved after the palette shipped, and moving it was safe *because* of
|
||||
* how the palette is stored: a named palette is honoured exactly as written,
|
||||
* so no stored document means anything different than it did. Only the
|
||||
* unwritten default moved, and any dashboard that dislikes where it moved to
|
||||
* can now name the old one. That inertness is the property worth keeping —
|
||||
* not this table, which is a design decision and may move again.
|
||||
* The slots a chart draws with: a named palette exactly as written, so no
|
||||
* stored document changes meaning, and otherwise the shared one in order.
|
||||
*/
|
||||
const SPREADS: Record<number, string[]> = {
|
||||
1: ["1"],
|
||||
2: ["1", "5"],
|
||||
3: ["1", "3", "5"],
|
||||
4: ["1", "2", "4", "5"],
|
||||
5: ["1", "2", "3", "4", "5"],
|
||||
}
|
||||
|
||||
/** The slots a chart of `count` lines draws with, named palette or not. */
|
||||
export function slotsFor(count: number, palette?: string[]): string[] {
|
||||
if (palette?.length) return palette
|
||||
return SPREADS[Math.min(Math.max(Math.trunc(count) || 1, 1), MAX_SERIES)]
|
||||
export function slotsFor(palette?: string[]): string[] {
|
||||
return palette?.length ? palette : CHART_SLOTS
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,9 +313,7 @@ export function UplotChart({
|
||||
let told: number | null = null
|
||||
/** Whether the click about to arrive is the end of a drag. */
|
||||
let dragging = false
|
||||
// Resolved once for the whole chart: how many lines there are is part of
|
||||
// which slots they take, when nothing named them.
|
||||
const slots = slotsFor(labels.length, palette)
|
||||
const slots = slotsFor(palette)
|
||||
// One builder for the whole chart: it is a factory, and the series only
|
||||
// need the function it returns.
|
||||
const spline = smooth ? { paths: uPlot.paths.spline?.() } : {}
|
||||
|
||||
Reference in New Issue
Block a user