Frutiger Aero theme, pixel-measured contrast fixes, sheet surfaces
Frutiger Aero (Settings -> Theme): a third theme, not a dark/light variant. A sky gradient with a strip of grass, the glacier blobs become clouds, the orbs soap bubbles, glass gets the classic horizon gloss and the buttons a glossy aqua. The light/dark toggles (header, rail, chat header) hide while it is on and the picker says why; the pre-paint script applies the class before first paint and the PWA status bar follows (#3fa3e0). Its muted/frost text is darker than Light's because those labels sit directly on the sky. Contrast, measured on real pixels (tests/contrast.mjs, now covering aero): - The light settings sheet was translucent over a dark scrim, so its muted text measured ~2.8:1. Sheets and dialogs now use --glass-sheet-bg (a more opaque surface), and Light's --text-muted is a touch darker. - Result: 0 below-minimum findings and 0 axe violations across every screen, all three themes, phone and desktop. Also: the suites now seed the cookie notice as already dismissed (they run as a returning user); the regression suite opts out to test the notice itself — the previous deploy failed its gate because the notice blocked a chat chip click. The notice also hides during immersive sessions (overlay-open), so it can never cover a study feed. Version 0.1.8, SW -> freezmo-v54.
This commit is contained in:
parent
464781a7fd
commit
e56653dae1
21 changed files with 329 additions and 57 deletions
|
|
@ -223,6 +223,41 @@ for (const locale of ["en", "cs"]) {
|
|||
|
||||
/* 5. axe-core contrast audit (360/390/desktop × dark/light × en/cs) -- */
|
||||
const AXE = axeSource();
|
||||
/* 6. frutiger aero: a third theme, no light/dark switch --------------- */
|
||||
{
|
||||
const { context, page } = await makePage(browser);
|
||||
await seed(page, { decks: [DECK], theme: "aero" });
|
||||
await page.goto(BASE, { waitUntil: "networkidle" });
|
||||
await page.waitForTimeout(900);
|
||||
const state = await page.evaluate(() => ({
|
||||
aero: document.documentElement.classList.contains("aero"),
|
||||
dark: document.documentElement.classList.contains("dark"),
|
||||
sky: getComputedStyle(document.documentElement).getPropertyValue("--ice-base-top").trim(),
|
||||
themeColor: document.querySelector('meta[name="theme-color"][data-app]')?.getAttribute("content"),
|
||||
}));
|
||||
check("aero: applied without the dark class", state.aero && !state.dark, JSON.stringify(state));
|
||||
check(
|
||||
"aero: the scene becomes a sky",
|
||||
state.sky.length > 0 && state.sky !== "#f4f9ff" && state.sky !== "#070b16",
|
||||
state.sky,
|
||||
);
|
||||
check("aero: the status bar follows the sky", state.themeColor === "#3fa3e0", String(state.themeColor));
|
||||
check(
|
||||
"aero: the light/dark toggle is gone",
|
||||
(await page.getByRole("button", { name: /Switch to (light|dark) mode/ }).count()) === 0,
|
||||
);
|
||||
await page.locator("nav.tabbar").getByRole("button").click();
|
||||
await page.getByRole("dialog").waitFor({ timeout: 6000 });
|
||||
await page.waitForTimeout(600);
|
||||
const picker = page.getByRole("group", { name: "Theme" });
|
||||
check(
|
||||
"aero: settings offers light, dark and aero",
|
||||
(await picker.count()) === 1 &&
|
||||
(await picker.getByRole("button", { name: "Frutiger Aero" }).getAttribute("aria-pressed")) === "true",
|
||||
);
|
||||
await context.close();
|
||||
}
|
||||
|
||||
async function audit(label, { width = 390, locale, theme, openSettingsNow }) {
|
||||
const { context, page } = await makePage(browser, { width, height: width >= 1280 ? 900 : 800, deviceScaleFactor: width >= 1280 ? 1 : 2 });
|
||||
await seed(page, { locale, theme, decks: [DECK] });
|
||||
|
|
@ -247,13 +282,13 @@ async function audit(label, { width = 390, locale, theme, openSettingsNow }) {
|
|||
await context.close();
|
||||
}
|
||||
for (const width of [360, 390, 1280]) {
|
||||
for (const theme of ["dark", "light"]) {
|
||||
for (const theme of ["dark", "light", "aero"]) {
|
||||
for (const locale of ["en", "cs"]) {
|
||||
await audit(`${width} ${theme}/${locale} library`, { width, locale, theme });
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const theme of ["dark", "light"]) {
|
||||
for (const theme of ["dark", "light", "aero"]) {
|
||||
for (const locale of ["en", "cs"]) {
|
||||
await audit(`390 ${theme}/${locale} settings`, { width: 390, locale, theme, openSettingsNow: true });
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue