commit b8dc5b801afba2eeb3ace3c53c436e08fe025a49
parent ac51e43166bbda046af9f034d386f9a8fa19fcf7
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Sun, 27 Sep 2026 01:02:11 -0400
hub, homepage(e2e): review nits — the no-accent hub colour is the chart colour; the colour spec requires the chart
ArchiveShelf's comment no longer says seriesColor() at its index; useHubSites'
paragraph is rewrapped. instance-colours.spec derives "a chart is drawn" from
the fixture summary's monthly series and asserts the chart and all n legend
swatches whenever it is, instead of skipping the legend checks when the page
has none.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
3 files changed, 36 insertions(+), 30 deletions(-)
diff --git a/export/app/components/hub/ArchiveShelf.tsx b/export/app/components/hub/ArchiveShelf.tsx
@@ -18,12 +18,13 @@
// order its ArchiveCards and growth chart draw in), and each wears the colour
// its homepage card wears (lib/siteColor.ts): its archive's OWN accent when the
// site sets one (the tool has no colour, the archives do) — a named accent at
-// its value on the base in force — and seriesColor() at its index in the
-// summary when it sets none. Order and colour are useHubSites'
-// (officialInstances), shared with the scope chips, the results' stripes and
-// /ask, so an archive is one colour on every surface. With no summary the order
-// is hub-sites.json's and the colour the card's place. An added archive with
-// no accent wears the family's signal colour.
+// its value on the base in force — and its homepage chart colour when it sets
+// none (siteChartColors: the palette slot at its index in the summary, or the
+// lowest free one when an accent's family holds that). Order and colour are
+// useHubSites' (officialInstances), shared with the scope chips, the results'
+// stripes and /ask, so an archive is one colour on every surface. With no
+// summary the order is hub-sites.json's and the colour the card's place. An
+// added archive with no accent wears the family's signal colour.
import { X } from "lucide-react";
import { Badge } from "yt-dlp-transcript-common/components/ui/badge";
diff --git a/export/app/components/hub/useHubSites.ts b/export/app/components/hub/useHubSites.ts
@@ -5,13 +5,14 @@
// and /ask: ONE order and ONE colour per archive, decided here.
//
// The official instances come in the homepage's order, each in the colour its
-// homepage card wears — its own accent (a named one per base), else the chart
-// palette's at its place (officialInstances, common/lib/hubSummary.ts). That order is /hub-summary.json's, so they are
-// listed only once that file has settled — found, missing or unreadable —
-// rather than in hub-sites.json's order first and reordered a moment later.
-// Both files are small, same-origin and requested together, so the wait is the
-// gap between two requests already in flight. The archives a visitor added
-// follow, in the order they were added, each in its own accent or none.
+// homepage card wears — its own accent (a named one per base), else its chart
+// colour (officialInstances, common/lib/hubSummary.ts). That order is
+// /hub-summary.json's, so they are listed only once that file has settled —
+// found, missing or unreadable — rather than in hub-sites.json's order first
+// and reordered a moment later. Both files are small, same-origin and
+// requested together, so the wait is the gap between two requests already in
+// flight. The archives a visitor added follow, in the order they were added,
+// each in its own accent or none.
import { useMemo } from "react";
import {
diff --git a/homepage/e2e/instance-colours.spec.ts b/homepage/e2e/instance-colours.spec.ts
@@ -18,11 +18,14 @@ import { FIXTURE_ACCENTS, FIXTURE_SUMMARY_NAME } from "./fixture-accents";
const BASE_KEY = "ytdlp-tb:base";
-function fixtureSites(): Array<{ accentId?: string }> | null {
+// The fixture copy the dev server reads: its sites, and whether it has the
+// monthly series the growth chart (and its legend) is drawn from.
+function fixture(): { sites: Array<{ accentId?: string }>; chart: boolean } | null {
try {
const file = path.resolve(test.info().project.testDir, FIXTURE_SUMMARY_NAME);
const s = JSON.parse(fs.readFileSync(file, "utf8"));
- return Array.isArray(s?.sites) && s.sites.length ? s.sites : null;
+ if (!Array.isArray(s?.sites) || s.sites.length === 0) return null;
+ return { sites: s.sites, chart: Array.isArray(s.monthly) && s.monthly.length > 0 };
} catch {
return null;
}
@@ -76,12 +79,13 @@ async function useBase(page: Page, base: "dark" | "light" | "sepia") {
test("each instance card wears its site's accent on every base, in its chart layer's hue", async ({
page,
}) => {
- const sites = fixtureSites();
- test.skip(!sites, "no summary on disk — the page has no instance cards");
- const n = sites!.length;
+ const f = fixture();
+ test.skip(!f, "no summary on disk — the page has no instance cards");
+ const { sites, chart: hasChart } = f!;
+ const n = sites.length;
expect(FIXTURE_ACCENTS[0].accentId).toBe("brass");
// The chart colours the page must wear, as the helper assigns them.
- const chart = siteChartColors(sites!);
+ const chart = siteChartColors(sites);
expect(chart[0]).toBe(`var(--chart-${ACCENT_CHART_SLOT.brass! + 1})`);
expect(new Set(chart).size).toBe(n);
await page.goto("/");
@@ -96,23 +100,23 @@ test("each instance card wears its site's accent on every base, in its chart lay
const { stripes, legend } = await colours(page);
expect(stripes).toHaveLength(n);
- // The legend (and so each layer) wears each site's chart colour.
- const hasChart = legend.length > 0;
- if (hasChart) {
- expect(legend).toHaveLength(n);
- for (let i = 0; i < n; i++) {
- expect(legend[i], `legend ${i}`).toBe(await resolve(page, chart[i]));
- }
+ // The summary's monthly series draws the chart, legend and all: the
+ // legend (and so each layer) wears each site's chart colour. A summary
+ // with none draws no chart at all.
+ await expect(
+ page.getByRole("img", { name: /transcripts by the month/i }),
+ ).toHaveCount(hasChart ? 1 : 0);
+ expect(legend, "legend swatches").toHaveLength(hasChart ? n : 0);
+ for (let i = 0; i < legend.length; i++) {
+ expect(legend[i], `legend ${i}`).toBe(await resolve(page, chart[i]));
}
// Site 0: the NAMED accent at this base's value — not the published
// on-dark hex on every base — and its legend swatch is the amber slot,
// the same hue family (a few degrees apart), at a different value.
expect(stripes[0]).toBe(await resolve(page, onBase[base]));
- if (hasChart) {
- expect(legend[0]).toBe(await resolve(page, "var(--chart-4)"));
- expect(hueGap(stripes[0], legend[0]), "brass vs its layer").toBeLessThan(25);
- }
+ expect(await resolve(page, chart[0])).toBe(await resolve(page, "var(--chart-4)"));
+ expect(hueGap(stripes[0], await resolve(page, chart[0])), "brass vs its layer").toBeLessThan(25);
// Site 1 (when there is one): the custom hex as published.
if (n > 1) expect(stripes[1]).toBe(await resolve(page, FIXTURE_ACCENTS[1].accent));
// Every other site has no accent: its chart colour, the same as its