commit 4776bc05739cddd9d556bb04f8dd2f7a2633fa84
parent 468e1ea559751c85b8563bdd7218ded975e31630
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Mon, 28 Sep 2026 00:22:25 -0400
e2e: the mark's ring on dark — each brand spec reads the computed box-shadow per base
The export, hub and homepage brand specs, and the editor's branding spec, now
check the ring BrandMark draws on the dark base, on the reader's stored base
after a reload:
- dark: the one visible box-shadow layer is `<dim> 0px 0px 0px 1px` — the
site header rgb(107, 93, 71) (#6b5d47), the parent marks (site footer
credit, hub header and footer, homepage header, editor sidebar)
rgb(88, 105, 119) (#586977) — with the corner at 21.875%;
- light and sepia (light only in the editor): no ring;
- the mark's box is 28 x 28 (16 x 16 in a footer) on every base, so the ring
takes no layout.
Tailwind's shadow composite lists four transparent layers before the ring;
the specs drop those and pin what is drawn.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
4 files changed, 193 insertions(+), 3 deletions(-)
diff --git a/editor/e2e/branding.spec.ts b/editor/e2e/branding.spec.ts
@@ -64,3 +64,34 @@ test("the sidebar carries the parent mark beside adminTitle, and the favicon is
expect(svg).toContain('fill="#151b20"');
expect(svg).toContain('fill="#e7edf1"');
});
+
+// The ring on dark (release 10, slice MR): on the dark base the sidebar mark's
+// slate tile gets a 1px ring outside it in the slate's dim (#586977), a
+// box-shadow following the ground's corner; on light, none.
+test("on dark the sidebar mark's tile has a 1px ring in its dim; on light none", async ({
+ page,
+}) => {
+ await page.goto("/");
+ const mark = page.locator("aside svg[data-brand-mark]");
+ const read = () =>
+ mark.evaluate((svg) => {
+ const cs = getComputedStyle(svg);
+ const layers = cs.boxShadow === "none" ? [] : cs.boxShadow.split(/,(?![^(]*\))/);
+ return {
+ dark: document.documentElement.classList.contains("dark"),
+ ring: layers.map((l) => l.trim()).filter((l) => !l.startsWith("rgba(0, 0, 0, 0)")),
+ radius: cs.borderTopLeftRadius,
+ };
+ });
+ for (const base of ["dark", "light"] as const) {
+ await page.evaluate((b) => localStorage.setItem("ytdlp-tb:base", b), base);
+ await page.reload();
+ await expect
+ .poll(read, { message: base })
+ .toEqual({
+ dark: base === "dark",
+ ring: base === "dark" ? ["rgb(88, 105, 119) 0px 0px 0px 1px"] : [],
+ radius: "21.875%",
+ });
+ }
+});
diff --git a/export/e2e-hub/brand.spec.ts b/export/e2e-hub/brand.spec.ts
@@ -1,4 +1,4 @@
-import { expect, test, type Route } from "@playwright/test";
+import { expect, test, type Locator, type Page, type Route } from "@playwright/test";
import { BASE_GROUNDS, ICON_PALETTES, markSvg } from "../../common/lib/brand";
// The hub is the family's own tool, so it wears the PARENT mark — bone on
@@ -48,3 +48,54 @@ test("the hub header is the parent mark + Archi|lyzer", async ({ page }) => {
);
expect(fills).toEqual(["rgb(21, 27, 32)", "rgb(88, 105, 119)", "rgb(231, 237, 241)"]);
});
+
+// The ring on dark (release 10, slice MR): on the dark base the tile has no
+// edge, so every mark's tile gets a 1px ring outside it in its palette's dim,
+// following the ground's corner (rx 112 of 512). A box-shadow, so the mark's
+// box is the same on every base; light and sepia draw none.
+const BASE_KEY = "ytdlp-tb:base";
+
+async function onBase(page: Page, base: "light" | "sepia" | "dark") {
+ await page.evaluate(([k, b]) => localStorage.setItem(k, b), [BASE_KEY, base]);
+ await page.reload({ waitUntil: "commit" });
+ await page.waitForFunction(() => document.documentElement?.dataset.themeReady === "1");
+ expect(await page.evaluate(() => document.documentElement.classList.contains("dark"))).toBe(
+ base === "dark",
+ );
+}
+
+// The mark's visible box-shadow layers (Tailwind's composite lists four
+// transparent ones before the ring), its corner, and its laid-out size.
+async function markRing(mark: Locator) {
+ return mark.evaluate((svg) => {
+ const cs = getComputedStyle(svg);
+ const r = svg.getBoundingClientRect();
+ const layers = cs.boxShadow === "none" ? [] : cs.boxShadow.split(/,(?![^(]*\))/);
+ return {
+ ring: layers.map((l) => l.trim()).filter((l) => !l.startsWith("rgba(0, 0, 0, 0)")),
+ radius: cs.borderTopLeftRadius,
+ size: [r.width, r.height],
+ };
+ });
+}
+
+test("on dark the hub's header and footer marks have a 1px ring in the slate's dim; on light and sepia none", async ({
+ page,
+}) => {
+ await page.route("**/hub-sites.json", (r) => fulfillJson(r, []));
+ await page.route("**/hub-summary.json", (r) => r.fulfill({ status: 404, body: "" }));
+ await page.goto("/");
+ const header = page.getByRole("banner").locator("svg[data-brand-mark]");
+ const footer = page.locator("footer svg[data-brand-mark]");
+
+ await onBase(page, "dark");
+ const ring = ["rgb(88, 105, 119) 0px 0px 0px 1px"]; // ICON_PALETTES.archilyzer.dim, #586977
+ expect(await markRing(header)).toEqual({ ring, radius: "21.875%", size: [28, 28] });
+ expect(await markRing(footer)).toEqual({ ring, radius: "21.875%", size: [16, 16] });
+
+ for (const base of ["light", "sepia"] as const) {
+ await onBase(page, base);
+ expect(await markRing(header), base).toEqual({ ring: [], radius: "21.875%", size: [28, 28] });
+ expect(await markRing(footer), base).toEqual({ ring: [], radius: "21.875%", size: [16, 16] });
+ }
+});
diff --git a/export/e2e/brand.spec.ts b/export/e2e/brand.spec.ts
@@ -1,4 +1,4 @@
-import { test, expect, type Locator } from "@playwright/test";
+import { test, expect, type Locator, type Page } from "@playwright/test";
import { ICON_PALETTES, childIconPalette, markSvg } from "../../common/lib/brand";
import { resolveAccent } from "../../common/lib/accent";
import { installRoutes } from "./helpers";
@@ -72,6 +72,63 @@ test("the header mark is the ink tile, its lit line following the reader's accen
expect(f.lit).not.toBe(f.dim);
});
+// The ring on dark (release 10, slice MR): on the dark base a site's ink tile
+// IS the page, so every mark's tile gets a 1px ring outside it in its own
+// palette's dim, following the ground's corner (rx 112 of 512). A box-shadow,
+// so the mark's box is the same on every base; light and sepia draw none.
+const BASE_KEY = "ytdlp-tb:base";
+
+async function onBase(page: Page, base: "light" | "sepia" | "dark") {
+ await page.evaluate(([k, b]) => localStorage.setItem(k, b), [BASE_KEY, base]);
+ await page.reload({ waitUntil: "commit" });
+ await page.waitForFunction(() => document.documentElement?.dataset.themeReady === "1");
+ expect(await page.evaluate(() => document.documentElement.classList.contains("dark"))).toBe(
+ base === "dark",
+ );
+}
+
+// The mark's visible box-shadow layers (Tailwind's composite lists four
+// transparent ones before the ring), its corner, and its laid-out size.
+async function markRing(mark: Locator) {
+ return mark.evaluate((svg) => {
+ const cs = getComputedStyle(svg);
+ const r = svg.getBoundingClientRect();
+ const layers = cs.boxShadow === "none" ? [] : cs.boxShadow.split(/,(?![^(]*\))/);
+ return {
+ ring: layers.map((l) => l.trim()).filter((l) => !l.startsWith("rgba(0, 0, 0, 0)")),
+ radius: cs.borderTopLeftRadius,
+ size: [r.width, r.height],
+ };
+ });
+}
+
+test("on dark the header and footer marks' tiles have a 1px ring in their dim; on light and sepia none", async ({
+ page,
+}) => {
+ await installRoutes(page);
+ await page.goto("/");
+ const header = page.getByRole("banner").locator("svg[data-brand-mark]");
+ const footer = page.locator("footer svg[data-brand-mark]");
+
+ await onBase(page, "dark");
+ expect(await markRing(header)).toEqual({
+ ring: ["rgb(107, 93, 71) 0px 0px 0px 1px"], // ICON_PALETTES.child.dim, #6b5d47
+ radius: "21.875%",
+ size: [28, 28],
+ });
+ expect(await markRing(footer)).toEqual({
+ ring: ["rgb(88, 105, 119) 0px 0px 0px 1px"], // ICON_PALETTES.archilyzer.dim, #586977
+ radius: "21.875%",
+ size: [16, 16],
+ });
+
+ for (const base of ["light", "sepia"] as const) {
+ await onBase(page, base);
+ expect(await markRing(header), base).toEqual({ ring: [], radius: "21.875%", size: [28, 28] });
+ expect(await markRing(footer), base).toEqual({ ring: [], radius: "21.875%", size: [16, 16] });
+ }
+});
+
test("the footer carries the parent mark before the credit, outside the link", async ({
page,
}) => {
diff --git a/homepage/e2e/brand.spec.ts b/homepage/e2e/brand.spec.ts
@@ -1,4 +1,4 @@
-import { expect, test } from "@playwright/test";
+import { expect, test, type Locator, type Page } from "@playwright/test";
import { ICON_PALETTES, markSvg } from "../../common/lib/brand";
// The project site wears the PARENT mark (plans/brand-and-themes.md, slice
@@ -36,3 +36,54 @@ test("the icon set is rendered from the parent mark", async ({ request }) => {
const ico = await request.get("/favicon.ico");
expect([...(await ico.body()).subarray(0, 4)]).toEqual([0, 0, 1, 0]);
});
+
+// The ring on dark (release 10, slice MR): on the dark base the tile has no
+// edge, so every mark's tile gets a 1px ring outside it in its palette's dim,
+// following the ground's corner (rx 112 of 512). A box-shadow, so the mark's
+// box is the same on every base; light and sepia draw none.
+const BASE_KEY = "ytdlp-tb:base";
+
+async function onBase(page: Page, base: "light" | "sepia" | "dark") {
+ await page.evaluate(([k, b]) => localStorage.setItem(k, b), [BASE_KEY, base]);
+ await page.reload({ waitUntil: "commit" });
+ await page.waitForFunction(() => document.documentElement?.dataset.themeReady === "1");
+ expect(await page.evaluate(() => document.documentElement.classList.contains("dark"))).toBe(
+ base === "dark",
+ );
+}
+
+// The mark's visible box-shadow layers (Tailwind's composite lists four
+// transparent ones before the ring), its corner, and its laid-out size.
+async function markRing(mark: Locator) {
+ return mark.evaluate((svg) => {
+ const cs = getComputedStyle(svg);
+ const r = svg.getBoundingClientRect();
+ const layers = cs.boxShadow === "none" ? [] : cs.boxShadow.split(/,(?![^(]*\))/);
+ return {
+ ring: layers.map((l) => l.trim()).filter((l) => !l.startsWith("rgba(0, 0, 0, 0)")),
+ radius: cs.borderTopLeftRadius,
+ size: [r.width, r.height],
+ };
+ });
+}
+
+test("on dark the header mark has a 1px ring in the slate's dim; on light and sepia none", async ({
+ page,
+}) => {
+ await page.goto("/");
+ const mark = page
+ .getByRole("link", { name: "Archilyzer home", exact: true })
+ .locator("svg[data-brand-mark]");
+
+ await onBase(page, "dark");
+ expect(await markRing(mark)).toEqual({
+ ring: ["rgb(88, 105, 119) 0px 0px 0px 1px"], // ICON_PALETTES.archilyzer.dim, #586977
+ radius: "21.875%",
+ size: [28, 28],
+ });
+
+ for (const base of ["light", "sepia"] as const) {
+ await onBase(page, base);
+ expect(await markRing(mark), base).toEqual({ ring: [], radius: "21.875%", size: [28, 28] });
+ }
+});