feat(ui): add light theme toggle #29

Merged
vince merged 4 commits from codex/light-mode-toggle into main 2026-06-20 01:17:48 +02:00
4 changed files with 83 additions and 10 deletions
Showing only changes of commit 0b2deb8405 - Show all commits

View file

@ -2,6 +2,8 @@ import { defineConfig, devices } from "@playwright/test";
const port = Number(process.env.PLAYWRIGHT_PORT || 4173); const port = Number(process.env.PLAYWRIGHT_PORT || 4173);
const baseURL = `http://127.0.0.1:${port}`; const baseURL = `http://127.0.0.1:${port}`;
const storybookPort = Number(process.env.PLAYWRIGHT_STORYBOOK_PORT || 6007);
const storybookURL = `http://127.0.0.1:${storybookPort}`;
const databaseUrl = const databaseUrl =
process.env.PLAYWRIGHT_DATABASE_URL || process.env.PLAYWRIGHT_DATABASE_URL ||
`file:./data/playwright-${process.pid}-${Date.now()}.sqlite`; `file:./data/playwright-${process.pid}-${Date.now()}.sqlite`;
@ -17,12 +19,20 @@ export default defineConfig({
trace: "retain-on-failure", trace: "retain-on-failure",
screenshot: "only-on-failure", screenshot: "only-on-failure",
}, },
webServer: { webServer: [
command: `DISABLE_LIVE_DATASOURCES=1 bun run build && DISABLE_LIVE_DATASOURCES=1 DATABASE_URL=${databaseUrl} HOST=127.0.0.1 PORT=${port} bun build/index.js`, {
url: baseURL, command: `DISABLE_LIVE_DATASOURCES=1 bun run build && DISABLE_LIVE_DATASOURCES=1 DATABASE_URL=${databaseUrl} HOST=127.0.0.1 PORT=${port} bun build/index.js`,
reuseExistingServer: false, url: baseURL,
timeout: 120_000, reuseExistingServer: false,
}, timeout: 120_000,
},
{
command: `[ -f storybook-static/iframe.html ] || bun run build-storybook; STORYBOOK_STATIC_PORT=${storybookPort} bun tests/e2e/storybook-server.ts`,
url: storybookURL,
reuseExistingServer: false,
timeout: 120_000,
},
],
projects: [ projects: [
{ {
name: "chromium-desktop", name: "chromium-desktop",

View file

@ -20,9 +20,7 @@ export const Light: Story = {
args: { args: {
theme: "light", theme: "light",
}, },
parameters: { globals: {
globals: { theme: "light",
theme: "light",
},
}, },
}; };

View file

@ -0,0 +1,33 @@
import { existsSync } from "node:fs";
import { resolve, sep } from "node:path";
const root = resolve(process.cwd(), "storybook-static");
const port = Number(process.env.STORYBOOK_STATIC_PORT || 6007);
if (!existsSync(resolve(root, "iframe.html"))) {
throw new Error("storybook-static is missing. Run bun run build-storybook first.");
}
Bun.serve({
hostname: "127.0.0.1",
port,
async fetch(request) {
const url = new URL(request.url);
const pathname = decodeURIComponent(url.pathname);
const relativePath = pathname === "/" ? "/index.html" : pathname;
const filePath = resolve(root, `.${relativePath}`);
if (!filePath.startsWith(`${root}${sep}`)) {
return new Response("Forbidden", { status: 403 });
}
const file = Bun.file(filePath);
if (!(await file.exists())) {
return new Response("Not found", { status: 404 });
}
return new Response(file);
},
});
console.log(`Storybook static listening on http://127.0.0.1:${port}`);

View file

@ -0,0 +1,32 @@
import { expect, test } from "@playwright/test";
const storybookPort = Number(process.env.PLAYWRIGHT_STORYBOOK_PORT || 6007);
const storybookURL = `http://127.0.0.1:${storybookPort}`;
test.describe("Storybook theme QA", () => {
test("renders the ThemeToggle light story on the light canvas", async ({
page,
}, testInfo) => {
test.skip(testInfo.project.name !== "chromium-desktop");
const consoleMessages: string[] = [];
page.on("console", (message) => {
if (["error", "warning"].includes(message.type())) {
consoleMessages.push(message.text());
}
});
const url = `${storybookURL}/iframe.html?id=ui-themetoggle--light&viewMode=story`;
await page.goto(url, { waitUntil: "networkidle" });
await expect(page.locator("html")).toHaveAttribute("data-ui-theme", "light");
await expect(
page.getByRole("button", { name: "Switch to dark theme" }),
).toBeVisible();
expect(
consoleMessages.filter((message) =>
message.includes("Global args/argTypes can only be set globally"),
),
).toEqual([]);
});
});