Startseite: groessere Kacheln, und das Licht folgt dem Zeiger

Rueckmeldung Filipe: "richtige richtung, die sollen nur bissl groesser
sein und noch bissl mehr spezieller."

GROESSER, gemessen statt geglaubt:
  Zeichenfeld  38 -> 46 px (Dashboard 56)
  Name        .93 -> 1.02 rem (Dashboard 1.18)
  Polsterung   14 -> 18 px, Ecken 15 -> 18 px
  Kachelhoehe        rund 60 -> ueber 80 px

Dabei fiel der eigene Test von vorhin sofort ein: Bei 880 px Seitenbreite
sind drei Kacheln je 285 px breit, und in den groesseren Schriften brach
der Text an ZWOELF Stellen ab. Statt die Schrift wieder zu verkleinern
bekommt die Startseite die volle Breite (1240 px) -- das ist die
ehrlichere Loesung. Hinweise, Begruessung und Fusstext behalten ihr Mass
von 940 px: Eine Textzeile ueber 1240 px zu ziehen macht sie nicht
lesbarer, sondern anstrengender.

SPEZIELLER, drei Dinge:

1. DAS LICHT FOLGT DEM ZEIGER. Jede Kachel traegt einen weichen
   Lichtfleck. Er sitzt ruhend oben links und wandert unter dem Zeiger
   mit. Kein Blinken, keine Bewegung des Inhalts -- es wird nur an einer
   anderen Stelle heller. Das ist die Kleinigkeit, die man nicht sieht,
   sondern erst beim Benutzen merkt.

   EIN Zuhoerer fuer alle Kacheln statt siebzehn, und in einem Bild je
   Rahmen: pointermove feuert dutzendfach je Sekunde, wer bei jedem
   Ereignis in den Stil schreibt, laesst den Browser umsonst rechnen.
   Beim Verlassen zurueck in die Ruhelage -- sonst blieben die Kacheln
   nach einer Weile alle unterschiedlich beleuchtet stehen. Auf
   Fingerbedienung und bei "weniger Bewegung" bleibt es ganz aus; dort
   gibt es keinen Zeiger, dem etwas folgen koennte. Beides geprueft.

2. Eine feine helle Linie an der Oberkante jeder Kachel. Ein Pixel, kaum
   sichtbar -- aber die Kachel wirkt dadurch von oben beleuchtet statt
   aufgeklebt. Das Zeichenfeld bekommt denselben Lichtrand und einen
   Verlauf, wodurch es gepraegt statt gemalt wirkt.

3. Beim Ueberfahren: farbiger Schein unter der Kachel im eigenen Ton,
   die Kante links waechst von 3 auf 4 px, das Zeichen um 4 Prozent.
   Alles unter zwei Pixeln Bewegung.

Die Trennlinie der Gruppenueberschriften laeuft nach rechts aus, statt
hart abzubrechen -- eine durchgezogene Linie zerschneidet die Seite, eine
auslaufende gliedert sie nur.

47 Pruefungen. Neu darunter: Zeichenfeld und Schriftgroesse werden
gemessen ("sieht groesser aus" ist kein Nachweis), und das Licht wird mit
echten Mausbewegungen an drei Stellen geprueft.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-08-31 22:50:17 +02:00
co-authored by Claude Opus 5
parent d05a772ee4
commit e25a22149b
22 changed files with 305 additions and 150 deletions
+55
View File
@@ -98,6 +98,9 @@ const lesen = (seite) => seite.evaluate(() => ({
hinweise: [...document.querySelectorAll("#dran .dran__punkt")]
.filter((z) => z.offsetParent !== null).length,
hinweiseGesamt: document.querySelectorAll("#dran .dran__punkt").length,
zeichenGroesse: Math.round(document.querySelector(".kachel__zeichen")?.getBoundingClientRect().width || 0),
namenGroesse: Math.round(parseFloat(getComputedStyle(document.querySelector(".kachel__name")).fontSize) || 0),
kachelHoehe: Math.round(document.querySelectorAll(".kachel")[1]?.getBoundingClientRect().height || 0),
zahlenLeer: !document.getElementById("zahlen-leer")?.hidden,
zahlen: [...document.querySelectorAll(".zahl")].length,
ueber: document.documentElement.scrollWidth - document.documentElement.clientWidth,
@@ -148,6 +151,13 @@ for (const [breite, wie] of [[1440, "Computer"], [390, "Handy"]]) {
ok(auf("LIVE-Analyse")?.zahl === "1", `der dringende Bereichspunkt (${auf("LIVE-Analyse")?.zahl})`);
ok(!auf("Wissens-Bibliothek")?.zahl, "wo nichts liegt, steht keine Zahl");
/* Die Kacheln sollen spürbar größer sein als vorher (Zeichenfeld 38px,
Name .93rem). Gemessen statt geglaubt -- "sieht größer aus" ist kein
Nachweis. */
ok(r.zeichenGroesse >= 46, `Zeichenfeld mindestens 46px (${r.zeichenGroesse}px)`);
ok(r.namenGroesse >= 16, `Name mindestens 16px (${r.namenGroesse}px)`);
ok(r.kachelHoehe >= 80, `Kachel mindestens 80px hoch (${r.kachelHoehe}px)`);
ok(r.abgeschnitten.length === 0,
`kein Text wird abgeschnitten (${r.abgeschnitten.join(" | ") || "keiner"})`);
ok(r.hinweise <= 4, `höchstens vier Hinweise sichtbar (${r.hinweise} von ${r.hinweiseGesamt})`);
@@ -206,6 +216,51 @@ console.log("\n=== Weniger Bewegung: keine Animation");
await kontext.close();
}
console.log("\n=== Das Licht folgt dem Zeiger");
{
const kontext = await browser.newContext({ viewport: { width: 1440, height: 1200 } });
const seite = await anmelden(kontext, "admin", "CODE-DOGI-0001");
const kachel = seite.locator(".kachel").nth(1);
const kasten = await kachel.boundingBox();
const ruhe = await kachel.evaluate((k) => k.style.getPropertyValue("--mx") || "(Ruhelage)");
ok(ruhe === "(Ruhelage)", `ruhend keine eigene Position gesetzt (${ruhe})`);
await seite.mouse.move(kasten.x + kasten.width * 0.2, kasten.y + kasten.height * 0.3);
await seite.waitForTimeout(250);
const links = await kachel.evaluate((k) => k.style.getPropertyValue("--mx"));
await seite.mouse.move(kasten.x + kasten.width * 0.85, kasten.y + kasten.height * 0.6);
await seite.waitForTimeout(250);
const rechts = await kachel.evaluate((k) => k.style.getPropertyValue("--mx"));
console.log(` links: ${links} · rechts: ${rechts}`);
ok(parseFloat(links) < 40, `links steht der Fleck links (${links})`);
ok(parseFloat(rechts) > 60, `rechts steht er rechts (${rechts})`);
/* Beim Verlassen zurück in die Ruhelage. Ohne das blieben die Kacheln
nach einer Weile alle unterschiedlich beleuchtet stehen, ohne dass
jemand wüsste, warum. */
await seite.mouse.move(kasten.x - 250, kasten.y - 250);
await seite.waitForTimeout(250);
const danach = await kachel.evaluate((k) => k.style.getPropertyValue("--mx") || "(Ruhelage)");
ok(danach === "(Ruhelage)", `nach dem Verlassen wieder in Ruhe (${danach})`);
await kontext.close();
}
console.log("\n=== Ohne feinen Zeiger bleibt es aus");
{
const kontext = await browser.newContext({
viewport: { width: 390, height: 844 }, hasTouch: true, isMobile: true });
const seite = await anmelden(kontext, "admin", "CODE-DOGI-0001");
await seite.touchscreen.tap(200, 700).catch(() => {});
await seite.waitForTimeout(200);
const gesetzt = await seite.evaluate(() =>
[...document.querySelectorAll(".kachel")].some((k) => k.style.getPropertyValue("--mx")));
ok(!gesetzt, "auf dem Handy wird nichts gesetzt");
await kontext.close();
}
await browser.close();
console.log(`\n${fehler === 0 ? "Alles in Ordnung." : fehler + " Prüfung(en) fehlgeschlagen."}`);
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* egal */ }