From e727fac4b780018d0ab3d7ef7a4f0be9000d6ab7 Mon Sep 17 00:00:00 2001 From: Andrei Laas Date: Wed, 16 Sep 2026 22:36:37 +0200 Subject: [PATCH] Der Streifen neben der Bildlaufleiste waren fuenfzig Schatten MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anmerkung 5, jetzt mit Ursache statt mit Vermutung. SlideOver bleibt geschlossen im DOM — absichtlich, sonst gaebe es keine Schiebebewegung. Geschlossen steht das Panel per translate-x-full hinter dem rechten Bildschirmrand, die eigene linke Kante genau auf dem Rand. Der Schatten ist das Einzige, was von dort noch ins Bild reicht: 32 px Weichzeichnung nach aussen, und aussen heisst hier nach links, in die Seite hinein. Bei einem Panel faellt das nicht auf. Die Protokollseite rendert aber eines **je Zeile** — AuditDetail haengt an jeder. Bei fuenfzig Lagen zu 18 % Deckkraft bleiben rechnerisch 0,01 % Durchsicht: ein fast schwarzer Streifen neben der Bildlaufleiste, mit Stufen dort, wo sich die Weichzeichnungen der einzelnen Lagen ueberlagern. Genau das war zu sehen, und genau deshalb nur auf dieser Seite. Die Tiefe gehoert zum geoeffneten Panel, nicht zum weggeschobenen. Sie erst beim Oeffnen zu setzen kostet nichts. Die Aenderung am Ueberlauf der Tabellenkarten aus dem vorigen Commit bleibt — sie war eine Aufraeumung, die fuer sich steht, aber nicht die Ursache. --- components/ui/SlideOver.tsx | 23 +++++++++- tests/components/SlideOver.test.tsx | 68 +++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 tests/components/SlideOver.test.tsx diff --git a/components/ui/SlideOver.tsx b/components/ui/SlideOver.tsx index 8042a09..ea33f26 100644 --- a/components/ui/SlideOver.tsx +++ b/components/ui/SlideOver.tsx @@ -36,8 +36,27 @@ export function SlideOver({ open, onClose, title, subtitle, children, footer }: aria-modal="true" aria-labelledby={titleId} tabIndex={-1} - className={`absolute right-0 top-0 flex h-dvh w-full max-w-md flex-col bg-white shadow-[var(--shadow-overlay)] outline-none transition-transform duration-200 ${ - open ? "translate-x-0" : "translate-x-full" + // ── Warum der Schatten am geschlossenen Panel wegfällt ────────── + // + // Geschlossen steht das Panel per `translate-x-full` genau hinter dem + // rechten Bildschirmrand: die eigene linke Kante liegt auf dem Rand. + // Der Schatten ist das Einzige, was von dort noch ins Bild reicht — + // 32 px Weichzeichnung nach aussen, und „aussen" heisst hier: nach + // links, in die Seite hinein. + // + // Bei einem Panel fällt das nicht auf. Die Protokollseite rendert + // jedoch eines **je Zeile**, also fünfzig übereinander an derselben + // Stelle. Bei 18 % Deckkraft bleiben nach fünfzig Lagen rechnerisch + // 0,01 % Durchsicht — ein fast schwarzer Streifen neben der + // Bildlaufleiste, mit sichtbaren Stufen dort, wo sich die + // Weichzeichnungen der einzelnen Lagen überlagern. Genau das hat der + // Kunde gemeldet. + // + // Die Tiefe gehört zum geöffneten Panel, nicht zum weggeschobenen. + // Sie erst beim Öffnen zu setzen kostet nichts und nimmt dem Stapel + // seine Wirkung. + className={`absolute right-0 top-0 flex h-dvh w-full max-w-md flex-col bg-white outline-none transition-transform duration-200 ${ + open ? "translate-x-0 shadow-[var(--shadow-overlay)]" : "translate-x-full" }`} >
diff --git a/tests/components/SlideOver.test.tsx b/tests/components/SlideOver.test.tsx new file mode 100644 index 0000000..58c1ea9 --- /dev/null +++ b/tests/components/SlideOver.test.tsx @@ -0,0 +1,68 @@ +import { render, screen } from "@testing-library/react"; +import { describe, expect, it } from "vitest"; +import { SlideOver } from "@/components/ui/SlideOver"; + +// Das Panel bleibt geschlossen im DOM, damit die Schiebebewegung laufen kann. +// Es steht dann per translate-x-full hinter dem rechten Bildschirmrand — die +// eigene linke Kante genau auf dem Rand. Ein Schatten reicht von dort noch +// ins Bild zurück, und die Protokollseite rendert ein Panel je Zeile: fünfzig +// Schatten an derselben Stelle ergaben einen fast schwarzen Streifen neben +// der Bildlaufleiste. + +function panel(container: HTMLElement): HTMLElement { + const el = container.querySelector('[role="dialog"]'); + expect(el, "Das Panel fehlt").not.toBeNull(); + return el as HTMLElement; +} + +describe("SlideOver", () => { + it("bleibt geschlossen im DOM", () => { + // Ohne das gäbe es keine Schiebebewegung beim Schliessen — und dieser + // Test hier hätte keinen Gegenstand. + const { container } = render( + {}} title="Titel"> + Inhalt + + ); + expect(panel(container).className).toContain("translate-x-full"); + }); + + it("trägt geschlossen keinen Schatten", () => { + const { container } = render( + {}} title="Titel"> + Inhalt + + ); + expect(panel(container).className).not.toContain("shadow-"); + }); + + it("trägt geöffnet einen Schatten", () => { + const { container } = render( + {}} title="Titel"> + Inhalt + + ); + expect(panel(container).className).toContain("shadow-[var(--shadow-overlay)]"); + expect(panel(container).className).toContain("translate-x-0"); + }); + + it("nimmt das geschlossene Panel aus der Bedienung", () => { + // `inert` und nicht aria-hidden: nur das entfernt die Felder auch aus der + // Tabulatorreihenfolge und blockiert Klicks. + const { container } = render( + {}} title="Titel"> + Inhalt + + ); + expect(panel(container).closest("[inert]")).not.toBeNull(); + }); + + it("benennt den Dialog nach seiner Überschrift", () => { + render( + {}} title="Anton Aigner"> + Inhalt + + ); + expect(screen.getByRole("dialog", { name: "Anton Aigner" })).toBeInTheDocument(); + }); +});