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>
BIN
docs/seed-kits/dark/01-list.png
Normal file
|
After Width: | Height: | Size: 301 KiB |
BIN
docs/seed-kits/dark/02-create-form.png
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
docs/seed-kits/dark/03-apply-dialog.png
Normal file
|
After Width: | Height: | Size: 264 KiB |
|
Before Width: | Height: | Size: 291 KiB After Width: | Height: | Size: 291 KiB |
|
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 163 KiB |
|
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 247 KiB |
@@ -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");
|
||||||
|
|||||||