From 4208676aa998e09f4dc24ed7bab44284c75a3edd Mon Sep 17 00:00:00 2001 From: marc Date: Fri, 18 Sep 2026 20:15:45 +0200 Subject: [PATCH] fix(ui): Platzhalter blitzt auch beim Tab-Wechsel nicht mehr auf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- frontend/src/components/Skeleton.tsx | 30 ++++++++++++++++ .../src/components/calendar/EventDialog.tsx | 2 +- frontend/src/pages/CalendarPage.tsx | 9 ++--- frontend/src/pages/FileBrowser.tsx | 36 +++---------------- frontend/src/pages/SharedPage.tsx | 5 +-- frontend/src/pages/SharedWithMePage.tsx | 11 ++++-- frontend/src/pages/TagsPage.tsx | 5 +-- frontend/src/pages/TrashPage.tsx | 5 +-- 8 files changed, 58 insertions(+), 45 deletions(-) diff --git a/frontend/src/components/Skeleton.tsx b/frontend/src/components/Skeleton.tsx index 78baa5f..f3bf97a 100644 --- a/frontend/src/components/Skeleton.tsx +++ b/frontend/src/components/Skeleton.tsx @@ -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 ( diff --git a/frontend/src/components/calendar/EventDialog.tsx b/frontend/src/components/calendar/EventDialog.tsx index 5e4bd82..7c734e4 100644 --- a/frontend/src/components/calendar/EventDialog.tsx +++ b/frontend/src/components/calendar/EventDialog.tsx @@ -292,7 +292,7 @@ export default function EventDialog({ event, defaultStart, calendars, calendarId