docs(seed-kits): add dark-mode screenshots alongside light

- Moves docs/seed-kits/*.png into docs/seed-kits/light/.
- Adds docs/seed-kits/dark/ with the same three panels rendered in
  the dark theme.
- Updates the capture script to loop over both themes by setting
  openconcho:theme in localStorage and the matching colorScheme on
  the browser context.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Agents
2026-05-24 21:26:40 +01:00
committed by Offending Commit
parent 650bfd7b28
commit 866dab39fe
7 changed files with 87 additions and 77 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

View File

Before

Width:  |  Height:  |  Size: 291 KiB

After

Width:  |  Height:  |  Size: 291 KiB

View File

Before

Width:  |  Height:  |  Size: 163 KiB

After

Width:  |  Height:  |  Size: 163 KiB

View File

Before

Width:  |  Height:  |  Size: 247 KiB

After

Width:  |  Height:  |  Size: 247 KiB

View File

@@ -1,94 +1,104 @@
// One-off screenshot capture for PR documentation. // One-off screenshot capture for PR documentation.
// Usage: BASE_URL=http://localhost:5177 node scripts/screenshot-seed-kits.mjs // Usage: BASE_URL=http://localhost:5177 node scripts/screenshot-seed-kits.mjs
//
// Produces both light- and dark-mode variants for each panel into
// docs/seed-kits/{light,dark}/.
import { mkdir } from "node:fs/promises"; import { mkdir } from "node:fs/promises";
import { resolve } from "node:path"; import { resolve } from "node:path";
import { chromium } from "@playwright/test"; import { chromium } from "@playwright/test";
const BASE_URL = process.env.BASE_URL ?? "http://localhost:5177"; const BASE_URL = process.env.BASE_URL ?? "http://localhost:5177";
const OUT_DIR = resolve(process.cwd(), "docs/seed-kits"); const OUT_ROOT = resolve(process.cwd(), "docs/seed-kits");
await mkdir(OUT_DIR, { recursive: true });
const browser = await chromium.launch(); const SEED_INSTANCES = {
const ctx = await browser.newContext({ instances: [
viewport: { width: 1440, height: 900 }, { id: "neo", name: "Neo (personal)", baseUrl: "http://localhost:8001", token: "" },
deviceScaleFactor: 2, { id: "jeeves", name: "Jeeves (CodeWalnut)", baseUrl: "http://localhost:8002", token: "" },
}); ],
activeId: "neo",
};
await ctx.addInitScript(() => { const SEED_KITS = [
window.localStorage.setItem( {
"openconcho:instances", id: "kit_ben_personal",
JSON.stringify({ name: "Ben — personal core",
instances: [ description: "Identity facts Ben wants every personal-tier agent to know.",
{ id: "neo", name: "Neo (personal)", baseUrl: "http://localhost:8001", token: "" }, lines: [
{ id: "jeeves", name: "Jeeves (CodeWalnut)", baseUrl: "http://localhost:8002", token: "" }, "Name: Ben Sheridan-Edwards",
], "Preferred address: Chief",
activeId: "neo", "Email: ben@codewalnut.com",
}), "Role: Founder",
"Github: BenSheridanEdwards",
],
},
{
id: "kit_codewalnut_context",
name: "CodeWalnut work context",
description: "Work-tier identity for Jeeves and any future CodeWalnut agents.",
lines: ["Employer: CodeWalnut", "Role: Founder", "Reports to: (self)"],
},
];
async function captureTheme(browser, theme) {
const outDir = resolve(OUT_ROOT, theme);
await mkdir(outDir, { recursive: true });
const ctx = await browser.newContext({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 2,
colorScheme: theme === "dark" ? "dark" : "light",
});
await ctx.addInitScript(
([instances, kits, themeValue]) => {
window.localStorage.setItem("openconcho:instances", instances);
window.localStorage.setItem("openconcho:seed-kits", kits);
window.localStorage.setItem("openconcho:theme", themeValue);
},
[JSON.stringify(SEED_INSTANCES), JSON.stringify(SEED_KITS), theme],
); );
window.localStorage.setItem(
"openconcho:seed-kits",
JSON.stringify([
{
id: "kit_ben_personal",
name: "Ben — personal core",
description: "Identity facts Ben wants every personal-tier agent to know.",
lines: [
"Name: Ben Sheridan-Edwards",
"Preferred address: Chief",
"Email: ben@codewalnut.com",
"Role: Founder",
"Github: BenSheridanEdwards",
],
},
{
id: "kit_codewalnut_context",
name: "CodeWalnut work context",
description: "Work-tier identity for Jeeves and any future CodeWalnut agents.",
lines: ["Employer: CodeWalnut", "Role: Founder", "Reports to: (self)"],
},
]),
);
});
const page = await ctx.newPage(); const page = await ctx.newPage();
async function shot(name, options = {}) { async function shot(name) {
const file = resolve(OUT_DIR, `${name}.png`); const file = resolve(outDir, `${name}.png`);
await page.screenshot({ path: file, fullPage: false, ...options }); await page.screenshot({ path: file, fullPage: false });
console.log("wrote", file); console.log("wrote", file);
}
// 1. List view with built-ins + user kits
await page.goto(`${BASE_URL}/seed-kits`, { waitUntil: "networkidle" });
await page.waitForSelector("text=Seed Kits");
await page.waitForTimeout(400); // settle animations
await shot("01-list");
// 2. Create form (use the "New kit" button)
await page
.getByRole("button", { name: /^New kit$/ })
.first()
.click();
await page.waitForSelector("text=New seed kit");
await page.waitForTimeout(300);
await shot("02-create-form");
// 3. Back to list, then open apply dialog on the first user kit
await page.goto(`${BASE_URL}/seed-kits`, { waitUntil: "networkidle" });
await page.waitForSelector("text=Ben — personal core");
await page.waitForTimeout(400);
const applyButtons = page.getByRole("button", { name: /^Apply$/ });
// User kits render after the 3 built-ins, so index 3 = first user kit.
await applyButtons.nth(3).click();
await page.waitForSelector("text=Apply seed kit");
await page.waitForTimeout(500);
await shot("03-apply-dialog");
await ctx.close();
} }
// 1. List view with built-ins + user kits const browser = await chromium.launch();
await page.goto(`${BASE_URL}/seed-kits`, { waitUntil: "networkidle" }); for (const theme of ["light", "dark"]) {
await page.waitForSelector("text=Seed Kits"); await captureTheme(browser, theme);
await page.waitForTimeout(400); // settle animations }
await shot("01-list");
// 2. Create form (use the "New kit" button)
await page
.getByRole("button", { name: /^New kit$/ })
.first()
.click();
await page.waitForSelector("text=New seed kit");
await page.waitForTimeout(300);
await shot("02-create-form");
// 3. Back to list, then open apply dialog on the "Ben — personal core" user kit
await page.goto(`${BASE_URL}/seed-kits`, { waitUntil: "networkidle" });
await page.waitForSelector("text=Ben — personal core");
await page.waitForTimeout(400);
// Find the Apply button next to "Ben — personal core" card
const benCard = page.locator("div", { hasText: /^Ben — personal core/ }).first();
// Just click the visible Apply button on that kit row
const applyButtons = page.getByRole("button", { name: /^Apply$/ });
const applyCount = await applyButtons.count();
// User kits are rendered after built-ins; the Ben card is the 4th apply button (0-3 built-ins, 4 = first user kit)
await applyButtons.nth(3).click();
await page.waitForSelector("text=Apply seed kit");
await page.waitForTimeout(500);
await shot("03-apply-dialog");
await browser.close(); await browser.close();
console.log("done"); console.log("done");