fix(ui): Platzhalter blitzt auch beim Tab-Wechsel nicht mehr auf

Die Frist von 220 ms galt nur beim Wechsel *innerhalb* der Dateiansicht. Beim
Wechsel zwischen den Menüpunkten entsteht die Seite jedes Mal neu – damit war
jeder Tab-Wechsel ein „erstes Laden", und genau dort war die Regel „beim ersten
Mal sofort zeigen" falsch herum. Die Frist gilt jetzt immer; 220 ms Leere ist
das ruhigere Bild, man kommt ohnehin von einer anderen Seite.

Als gemeinsamer Haken `useSkeleton`, statt die Logik in fünf Seiten zu
wiederholen.

Dabei wäre beinahe ein schlimmerer Geist entstanden: Im Wartefenster hat kurz
der **Leerzustand** aufgeblitzt – „Nothing shared with you yet", eine
Zehntelsekunde bevor die Liste kam. Der Platzhalter sieht nur nach Daten aus,
ein Satz behauptet etwas. Das Wartefenster bleibt jetzt überall leer.

Dazu drei Reste der Kalender-Übersetzung, die mein Suchmuster übersehen hatte,
weil sie in Template-Strings standen: der Löschen-Dialog des Kalenders und der
Wochentag-Hinweis im Terminfenster. Und das Datum in der Listenansicht stand
noch im deutschen Format („18. September 2026") in einer englischen
Oberfläche – jetzt „September 18, 2026".

Geprüft: tsc sauber, 41 Vitest-Tests, alle 234 Prüfungen der sieben
Selbsttest-Suiten grün.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
marcandClaude Opus 5 committed 2026-09-18 20:15:45 +02:00
1 parent 0591a40d12
commit 4208676aa9
8 files changed
+58 -45

No files matched your search

+30
View File
@@ -1,3 +1,5 @@
import { useEffect, useState } from 'react'
/**
* Platzhalter, solange geladen wird.
*
@@ -13,6 +15,34 @@
* Zweck wäre dahin.
*/
/**
* Zeigen wir den Platzhalter **wirklich** – oder ist die Liste schneller da?
*
* Ohne Frist blitzt bei jedem Ordnerwechsel und bei jedem Tab-Wechsel kurz ein
* Feld grauer Kästen auf. Sie sehen aus wie Dateien, die sofort wieder
* verschwinden; Marc nannte sie „Geister", und das trifft es: Der Platzhalter
* soll Warten überbrücken, nicht Warten erfinden.
*
* **Die Frist gilt auch beim allerersten Laden.** Das war zuerst anders – ich
* hatte gedacht, beim ersten Mal gebe es ja nichts, was stehenbleiben könnte,
* also könne er sofort kommen. Beim Wechsel zwischen den Menüpunkten entsteht
* die Seite aber jedes Mal neu, und damit war *jeder* Tab-Wechsel ein „erstes
* Laden". Genau dort blitzte es dann. 220 ms Leere ist das ruhigere Bild: Man
* kommt ohnehin von einer anderen Seite, der Wechsel liest sich als Wechsel.
*
* 220 ms ist die Grenze, ab der ein Wechsel als „hakt" empfunden wird –
* darunter merkt niemand, dass überhaupt geladen wurde.
*/
export function useSkeleton(loading: boolean, frist = 220): boolean {
const [zeigen, setZeigen] = useState(false)
useEffect(() => {
if (!loading) { setZeigen(false); return }
const t = setTimeout(() => setZeigen(true), frist)
return () => clearTimeout(t)
}, [loading, frist])
return zeigen
}
/** Ein graues Feld, das leicht pulsiert. */
function Feld({ w, h, r = 6, mb }: { w: number | string; h: number; r?: number; mb?: number }) {
return (
@@ -292,7 +292,7 @@ export default function EventDialog({ event, defaultStart, calendars, calendarId
<button
key={code} type="button" disabled={readOnly || fixed}
onClick={() => toggleDay(code)}
title={fixed ? `${weekdayLong[i]} – Tag des Starts` : weekdayLong[i]}
title={fixed ? `${weekdayLong[i]} – the day the event starts` : weekdayLong[i]}
style={{
flex: 1, padding: '6px 0', borderRadius: 7, fontSize: 12,
border: '1px solid var(--color-border)',