Phones get flat glass: no live blur, no baked layer
The touch fallback from 0.3.8 (a real backdrop-filter over the live scene) was the wrong trade: every pane re-blurs on every frame while the bubbles animate, and phones choke - input lag, "buttons take ages to respond". Touch devices now drop both the bake (which mispaints there) and the live blur: the panes keep the thin Ask-pill tint over the sharp scene, and the hand-rolled activity fills keep their own tints - transparent glass at zero per-frame cost. Desktop keeps the baked blur. tests/mobile-test.mjs pins the flat contract (no baked layer, no backdrop-filter on a card) with a touch context: 124/124. Contrast 0 findings, axe clean, chat 101/101, regression 44/44, i18n 13/13, native 33/33. Version 0.3.9, SW -> freezmo-v68.
This commit is contained in:
parent
b315e2a1aa
commit
2b78dcf0d1
5 changed files with 29 additions and 17 deletions
|
|
@ -1411,6 +1411,15 @@ Things I chose while building, with the reasoning:
|
||||||
pre-blurred wallpaper — the scene is clearly visible through the glass, and the
|
pre-blurred wallpaper — the scene is clearly visible through the glass, and the
|
||||||
pixel-contrast scan still passes.
|
pixel-contrast scan still passes.
|
||||||
|
|
||||||
|
74. **Phones get flat glass, not live blur.** The touch fallback from 73 (a real backdrop blur
|
||||||
|
over the live scene) turned out to be the wrong trade: every pane re-blurs on every frame
|
||||||
|
while the bubbles animate, and phones choke — input lag, "buttons take ages to respond". Touch
|
||||||
|
devices now drop both the bake (which mispaints there) *and* the live blur: the panes keep the
|
||||||
|
thin Ask-pill tint over the sharp scene (the hand-rolled activity fills keep their own tints),
|
||||||
|
i.e. transparent glass at zero per-frame cost. Desktop keeps the baked blur — the same look as
|
||||||
|
the phones had, without the GPU bill. `tests/mobile-test.mjs` pins the flat contract (no baked
|
||||||
|
layer, no backdrop-filter on a card) with a touch context.
|
||||||
|
|
||||||
73. **Touch devices blur the live backdrop; desktop keeps the bake.** Mobile engines repaint
|
73. **Touch devices blur the live backdrop; desktop keeps the bake.** Mobile engines repaint
|
||||||
`background-attachment: fixed` late (and iOS treats it as scroll), so the baked glass showed a
|
`background-attachment: fixed` late (and iOS treats it as scroll), so the baked glass showed a
|
||||||
stale crop of the wallpaper until a tap forced a repaint — "some of the UI looks bugged until I
|
stale crop of the wallpaper until a tap forced a repaint — "some of the UI looks bugged until I
|
||||||
|
|
|
||||||
|
|
@ -597,13 +597,14 @@
|
||||||
background-repeat: no-repeat, no-repeat;
|
background-repeat: no-repeat, no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Touch devices: the baked backdrop is `background-attachment: fixed`, which
|
/* Touch devices: flat glass, no bake and no live blur. The baked layer is
|
||||||
mobile engines repaint late (and iOS treats as scroll) — panes showed a
|
`background-attachment: fixed`, which mobile engines repaint late (iOS
|
||||||
stale crop of the wallpaper until a tap forced a repaint ("some UI looks
|
treats it as scroll) — panes showed a stale crop until a tap forced a
|
||||||
bugged until I click it"). Touch hardware has the GPU budget for the honest
|
repaint. The honest alternative (a real backdrop-filter) is worse: every
|
||||||
version instead: a real backdrop blur over the live scene, so the bubbles
|
pane re-blurs on every frame while the bubbles animate, and phones choke —
|
||||||
blur through the glass as they pass. Desktop keeps the bake (measured
|
measured as input lag, "buttons take ages to respond". So on touch the
|
||||||
cheaper there, and verified correct). */
|
panes keep the thin Ask-pill tint over the sharp scene: transparent glass
|
||||||
|
at zero per-frame cost. Desktop keeps the baked blur. */
|
||||||
@media (max-width: 639px), (pointer: coarse) {
|
@media (max-width: 639px), (pointer: coarse) {
|
||||||
.aero .card,
|
.aero .card,
|
||||||
.aero .glass-solid,
|
.aero .glass-solid,
|
||||||
|
|
@ -618,16 +619,18 @@
|
||||||
.aero .btn-secondary,
|
.aero .btn-secondary,
|
||||||
.aero .btn-primary,
|
.aero .btn-primary,
|
||||||
.aero .grad-ice,
|
.aero .grad-ice,
|
||||||
.aero .segmented,
|
.aero .segmented {
|
||||||
.aero .segmented > button[aria-pressed="true"],
|
|
||||||
.aero .segmented > a[aria-current="page"],
|
|
||||||
.aero .chat-bubble,
|
|
||||||
.aero .chat-answer {
|
|
||||||
background-image: none;
|
background-image: none;
|
||||||
@apply backdrop-blur-md backdrop-saturate-[1.4];
|
background-color: rgb(255 255 255 / 0.32);
|
||||||
|
}
|
||||||
|
.aero .segmented > button[aria-pressed="true"],
|
||||||
|
.aero .segmented > a[aria-current="page"] {
|
||||||
|
background-image: none;
|
||||||
|
background-color: rgb(255 255 255 / 0.45);
|
||||||
}
|
}
|
||||||
.aero .chat-bubble,
|
.aero .chat-bubble,
|
||||||
.aero .chat-answer {
|
.aero .chat-answer {
|
||||||
|
background-image: none;
|
||||||
background-color: rgb(255 255 255 / 0.55);
|
background-color: rgb(255 255 255 / 0.55);
|
||||||
}
|
}
|
||||||
.aero .tabbar {
|
.aero .tabbar {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "freezmo",
|
"name": "freezmo",
|
||||||
"version": "0.3.8",
|
"version": "0.3.9",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
* Bumping CACHE_VERSION is how a new deploy invalidates old assets.
|
* Bumping CACHE_VERSION is how a new deploy invalidates old assets.
|
||||||
*/
|
*/
|
||||||
const CACHE_VERSION = "freezmo-v67";
|
const CACHE_VERSION = "freezmo-v68";
|
||||||
const SHELL_CACHE = `${CACHE_VERSION}-shell`;
|
const SHELL_CACHE = `${CACHE_VERSION}-shell`;
|
||||||
const ASSET_CACHE = `${CACHE_VERSION}-assets`;
|
const ASSET_CACHE = `${CACHE_VERSION}-assets`;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -295,13 +295,13 @@ const AXE = axeSource();
|
||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
const glass = await page.evaluate(() => {
|
const glass = await page.evaluate(() => {
|
||||||
const coarsish = matchMedia("(pointer: coarse)").matches || matchMedia("(max-width: 639px)").matches;
|
const coarsish = matchMedia("(pointer: coarse)").matches || matchMedia("(max-width: 639px)").matches;
|
||||||
const el = document.querySelector(".segmented");
|
const el = document.querySelector(".card");
|
||||||
const cs = getComputedStyle(el);
|
const cs = getComputedStyle(el);
|
||||||
return { coarsish, backdrop: cs.backdropFilter, image: cs.backgroundImage };
|
return { coarsish, backdrop: cs.backdropFilter, image: cs.backgroundImage };
|
||||||
});
|
});
|
||||||
check(
|
check(
|
||||||
"theme: touch glass blurs the live backdrop (no baked layer)",
|
"theme: touch glass is flat (no bake, no per-frame blur)",
|
||||||
glass.coarsish && glass.backdrop.includes("blur") && glass.image === "none",
|
glass.coarsish && glass.backdrop === "none" && glass.image === "none",
|
||||||
JSON.stringify(glass),
|
JSON.stringify(glass),
|
||||||
);
|
);
|
||||||
await context.close();
|
await context.close();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue