Verwaltung: gleitender Leuchtbalken, gestaffelte Kacheln, Reiterlicht
Drei weitere Stufen auf der Buehne.
1. DER GLEITENDE LEUCHTBALKEN
Unter der Reiterreihe liegt ein Balken in der Leitfarbe. Beim Wechsel
springt er nicht, sondern gleitet zum neuen Reiter und faerbt sich dabei
um.
Position und Breite kommen aus dem ECHTEN Reiter, im Browser gemessen.
Feste Werte waeren hier zwangslaeufig falsch: Die Reiter sind
unterschiedlich breit ("Kunden" gegen "Zahlungen"), sie verschieben sich
beim Sprachwechsel, und auf schmalen Schirmen brechen sie um -- deshalb
wandert auch die Hoehe mit, nicht nur die Seite.
2. DIE KACHELN TAUCHEN GESTAFFELT AUF
Beim Bereichswechsel erscheinen sie nacheinander statt alle auf einmal.
Nur die ersten acht bekommen einen Versatz -- bei einer langen Liste
kaeme die letzte Kachel sonst spuerbar spaeter, und das fuehlt sich
nicht mehr elegant an, sondern langsam.
3. DAS LICHT FOLGT AUCH AUF DEN REITERN
Die Verfolgung im Grundsystem greift ausdruecklich nur auf Karten. Fuer
die Reiter ist sie hier ergaenzt, gedrosselt ueber
requestAnimationFrame -- aus demselben Grund wie dort.
ZWEI FEHLER, DIE DER TEST GEFUNDEN HAT:
Der Balken stand auf Breite 0 und blieb unsichtbar. Ein blosser
"resize"-Horcher reicht naemlich nicht: Der haeufigste Fall ist gar
keine Fenstergroessenaenderung, sondern das Sichtbarwerden. Beim Start
ist der Arbeitsbereich versteckt, die Leiste also 0 Punkte breit -- und
ein verstecktes Element loest kein resize aus. Jetzt beobachtet ein
ResizeObserver die Leiste; das deckt Sichtbarwerden, Umbrechen und
Sprachwechsel gleichermassen ab.
Und die Messung hing allein am Klick-Listener. Wechselt der Bereich auf
einem anderen Weg -- etwa direkt nach dem Anmelden, wenn der
Arbeitsbereich zum ersten Mal auftaucht -- wurde nie nachgemessen.
balkenSetzen ist deshalb jetzt nach aussen verfuegbar.
Alles Bewegte bleibt bei prefers-reduced-motion aus: kein Gleiten, kein
Auftauchen, keine Parallaxe, kein Reflex. Die Buehne bleibt sichtbar.
Ein Wort zum Test selbst: Er prueft "der Balken springt" nicht mehr auf
wortwoertlich "0s". Die Testumgebung emuliert reduzierte Bewegung, indem
sie Uebergaenge auf eine Mikrosekunde setzt statt auf null -- gemeldet
wird "1e-06s". Wahrnehmbar ist das identisch; ein Test auf exakt "0s"
haette nur die Emulation gemessen, nicht die Regel.
Geprueft: 244 Pruefungen gruen (Verwaltung 46, Portfolio 15, CRYONOVA 53,
Blickfang 13, System 5, Abmelden 16, Abbruch 42, Angebot 54).
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -287,6 +287,78 @@ srv.listen(4404, async () => {
|
||||
const weite = Math.max(...String(lage2).match(/-?[\d.]+/g).map((n) => Math.abs(+n)));
|
||||
pruefe("und zwar nur wenige Bildpunkte", weite <= 16, weite.toFixed(1) + "px");
|
||||
|
||||
console.log("\n===== 3d. DER LEUCHTBALKEN =====");
|
||||
/* Der Balken muss GENAU am aktiven Reiter sitzen. Gemessen wird
|
||||
gegen die echten Masse des Reiters -- feste Werte waeren hier
|
||||
zwangslaeufig falsch, weil die Reiter unterschiedlich breit sind
|
||||
und beim Sprachwechsel wandern. */
|
||||
const balkenPruefen = async (bereich) => {
|
||||
/* Erst den Bereich sichtbar machen, DANN klicken: Ein Klick auf
|
||||
einen zugeklappten Arbeitsbereich misst zwangslaeufig 0.
|
||||
Danach wieder aufmachen -- der Klick loest die Zugangspruefung
|
||||
aus, die korrekterweise zur Anmeldung zurueckschaltet. */
|
||||
await bereichAufbauen(seite, bereich);
|
||||
await seite.click(`[data-tab="${bereich}"]`).catch(() => {});
|
||||
await seite.waitForTimeout(500);
|
||||
await bereichAufbauen(seite, bereich);
|
||||
await seite.evaluate(() => window.vwBalkenSetzen && window.vwBalkenSetzen());
|
||||
await seite.waitForTimeout(400);
|
||||
return seite.evaluate(() => {
|
||||
const l = document.querySelector("#vw-bereich .vw-tabs");
|
||||
const a = l.querySelector(".vw-filter-knopf.vw-an");
|
||||
const lr = l.getBoundingClientRect();
|
||||
const ar = a.getBoundingClientRect();
|
||||
const st = l.style;
|
||||
return {
|
||||
gesetztX: parseInt(st.getPropertyValue("--vw-balken-x"), 10),
|
||||
gesetztB: parseInt(st.getPropertyValue("--vw-balken-b"), 10),
|
||||
echtX: Math.round(ar.left - lr.left),
|
||||
echtB: Math.round(ar.width),
|
||||
sichtbar: st.getPropertyValue("--vw-balken-da"),
|
||||
reiter: a.textContent.trim().slice(0, 12),
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const b1 = await balkenPruefen("uebersicht");
|
||||
pruefe("der Balken sitzt am aktiven Reiter",
|
||||
Math.abs(b1.gesetztX - b1.echtX) <= 2 && Math.abs(b1.gesetztB - b1.echtB) <= 2,
|
||||
`${b1.reiter}: gesetzt ${b1.gesetztX}/${b1.gesetztB}, echt ${b1.echtX}/${b1.echtB}`);
|
||||
pruefe("und er ist sichtbar", b1.sichtbar === "1", b1.sichtbar);
|
||||
/* Der haeufigste Fehlerfall: Beim Start ist der Arbeitsbereich noch
|
||||
versteckt, die Leiste also 0 Punkte breit. Wer nur auf "resize"
|
||||
horcht, misst nie nach -- der Balken bleibt auf Breite 0. */
|
||||
pruefe("er hat eine echte Breite (nicht 0)", b1.gesetztB > 20, b1.gesetztB + "px");
|
||||
|
||||
const b2 = await balkenPruefen("zahlungen");
|
||||
pruefe("er wandert zum neuen Reiter mit",
|
||||
b2.gesetztX !== b1.gesetztX && Math.abs(b2.gesetztX - b2.echtX) <= 2,
|
||||
`${b1.gesetztX}px -> ${b2.gesetztX}px`);
|
||||
|
||||
console.log("\n===== 3e. TAUCHEN DIE KACHELN GESTAFFELT AUF? =====");
|
||||
const staffel = await seite.evaluate(() => {
|
||||
const be = document.querySelector("#vw-bereich");
|
||||
const probe = document.querySelector("#vw-probe");
|
||||
probe.innerHTML = "";
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const k = document.createElement("div");
|
||||
k.className = "wd-karte";
|
||||
k.style.padding = "1rem";
|
||||
k.textContent = "Kachel " + (i + 1);
|
||||
probe.appendChild(k);
|
||||
}
|
||||
return [...probe.querySelectorAll(".wd-karte")].map((k) => ({
|
||||
name: getComputedStyle(k).animationName,
|
||||
versatz: getComputedStyle(k).animationDelay,
|
||||
}));
|
||||
});
|
||||
pruefe("die Kacheln haben eine Auftauch-Animation",
|
||||
staffel.every((k) => k.name === "vw-kachel-auf"),
|
||||
staffel.map((k) => k.name).join(", "));
|
||||
pruefe("und jede startet etwas spaeter als die davor",
|
||||
new Set(staffel.map((k) => k.versatz)).size === staffel.length,
|
||||
staffel.map((k) => k.versatz).join(" "));
|
||||
|
||||
console.log("\n===== 4. WECHSELT DER RAUM WIRKLICH? =====");
|
||||
const gesehen = [];
|
||||
for (const bereich of BEREICHE) {
|
||||
@@ -344,6 +416,30 @@ srv.listen(4404, async () => {
|
||||
});
|
||||
pruefe("keine Parallaxe bei reduzierter Bewegung",
|
||||
ruhigeLage.translate === "none", ruhigeLage.translate);
|
||||
const ruhigExtra = await ruhig.evaluate(() => {
|
||||
const be = document.querySelector("#vw-bereich");
|
||||
const k = document.createElement("div");
|
||||
k.className = "wd-karte";
|
||||
be.appendChild(k);
|
||||
const l = document.querySelector("#vw-bereich .vw-tabs");
|
||||
return {
|
||||
kachel: getComputedStyle(k).animationName,
|
||||
balken: getComputedStyle(l, "::after").transitionDuration,
|
||||
};
|
||||
});
|
||||
pruefe("keine Auftauch-Animation der Kacheln",
|
||||
ruhigExtra.kachel === "none", ruhigExtra.kachel);
|
||||
/* Geprueft wird "praktisch sofort", nicht wortwoertlich "0s".
|
||||
|
||||
Die Testumgebung emuliert reduzierte Bewegung, indem sie alle
|
||||
Uebergaenge auf eine Mikrosekunde setzt statt auf null -- gemeldet
|
||||
wird dann "1e-06s". Wahrnehmbar ist das identisch; ein Test auf
|
||||
exakt "0s" wuerde nur die Emulation messen, nicht die Regel. */
|
||||
const laengste = Math.max(...ruhigExtra.balken.split(",")
|
||||
.map((t) => parseFloat(t) || 0));
|
||||
pruefe("und der Balken gleitet nicht, sondern springt",
|
||||
laengste <= 0.01, ruhigExtra.balken);
|
||||
|
||||
pruefe("und kein Lichtreflex",
|
||||
ruhigeLage.reflex === "none" && ruhigeLage.reflexSichtbar === 0,
|
||||
ruhigeLage.reflex + ", Deckkraft " + ruhigeLage.reflexSichtbar);
|
||||
|
||||
Reference in New Issue
Block a user