From b865cf49bd853c509bd5e2876723d34ac40e4cf3 Mon Sep 17 00:00:00 2001 From: Florian Wilde Date: Sat, 25 Jul 2026 22:46:00 +0200 Subject: [PATCH] fix(ui): Anzeigefehler aus der Browser-Pruefung beheben Erstmals mit echtem Browser nachgesehen (headless Chrome ueber Playwright, Screenshots aller Ansichten). Dabei fuenf Dinge gefunden: 1. Menue klebte am Fensterrand statt am Ausloeser. Bei einem Ausloeser weit links wurde die bevorzugte rechtsbuendige Ausrichtung negativ und dann auf den Rand geklemmt - das Menue stand quer ueber der Seite. Jetzt wird bei Ueberlauf auf die andere Ausrichtung gewechselt und erst danach geklemmt. 2. .popover war mit 97 % nicht ganz deckend, wodurch "Bearbeiten" und "Loeschen" schwach durchschienen. Jetzt vollstaendig deckend. 3. Der Schieberegler zeichnete die Spur rechts vom Griff in einem hellen Standardton - ein grelles Band im dunklen Layout. Ersetzt durch eine selbst gezeichnete Variante mit Farbverlauf und sichtbarem Griff. Auf der Projektseite ersetzt sie zugleich das bisherige unsichtbare Eingabefeld ueber einem gezeichneten Balken, das gar keinen Griff hatte. 4. Der Hinweis der Kachel "Ideen" wurde mitten im Wort abgeschnitten ("Noch ein Gedanke - nichts ge..."). Kurzer Text statt der langen Statusbeschreibung. 5. Nach der Einrichtung stand im Adminbereich "noch nie angemeldet", obwohl gerade eine Sitzung lief. Einrichtung und Registrierung setzen lastLoginAt jetzt mit. Die Konsole blieb ueber alle Ansichten hinweg frei von Fehlern und Warnungen - die strikte CSP mit Nonce und strict-dynamic bricht also nichts. Geprueft an einer separaten Wegwerf-Datenbank auf Port 3100, damit die laufende Instanz unberuehrt blieb. Co-Authored-By: Claude Opus 5 (1M context) --- src/app/api/auth/register/route.ts | 2 + src/app/api/auth/setup/route.ts | 3 ++ src/app/components.css | 61 +++++++++++++++++++++++++++++- src/app/page.tsx | 4 +- src/components/ProjectDialog.tsx | 3 +- src/components/ProjectHeader.tsx | 37 ++++++++---------- src/components/ui/Popover.tsx | 6 +++ 7 files changed, 92 insertions(+), 24 deletions(-) diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts index 912d72e..3f69af8 100644 --- a/src/app/api/auth/register/route.ts +++ b/src/app/api/auth/register/route.ts @@ -69,6 +69,8 @@ export async function POST(request: Request) { email: email ?? null, passwordHash: await hashPassword(password), role: "USER", + // Die Registrierung meldet direkt an. + lastLoginAt: new Date(), }, }); diff --git a/src/app/api/auth/setup/route.ts b/src/app/api/auth/setup/route.ts index b3fe52c..b0db2f6 100644 --- a/src/app/api/auth/setup/route.ts +++ b/src/app/api/auth/setup/route.ts @@ -49,6 +49,9 @@ export async function POST(request: Request) { email: email ?? null, passwordHash: await hashPassword(password), role: "ADMIN", + // Die Einrichtung meldet direkt an – sonst stuende im Adminbereich + // "noch nie angemeldet", obwohl gerade eine Sitzung laeuft. + lastLoginAt: new Date(), }, }); diff --git a/src/app/components.css b/src/app/components.css index c8f6f67..d58acb0 100644 --- a/src/app/components.css +++ b/src/app/components.css @@ -79,7 +79,9 @@ * Weichzeichnung wirkungslos. */ .popover { - background: rgba(9, 11, 24, 0.97); + /* Vollstaendig deckend: bei 97 % schimmerte darunterliegender Text + (die Schaltflaechen "Bearbeiten" und "Loeschen") noch durch. */ + background: #090b18; border: 1px solid rgba(255, 255, 255, 0.11); border-radius: 0.9rem; box-shadow: @@ -208,4 +210,61 @@ background: #0a0c1a; color: #e6e8f5; } + + /** + * Schieberegler. Der native Regler zeichnet die Spur rechts vom Griff in + * einem hellen Standardton - im dunklen Layout ein grelles Band. Deshalb + * vollstaendig selbst gezeichnet: der gefuellte Anteil kommt aus der + * Variablen --fill, die die Komponente aus dem Wert setzt. + */ + .range { + -webkit-appearance: none; + appearance: none; + width: 100%; + height: 6px; + border-radius: 9999px; + cursor: pointer; + background: linear-gradient( + 90deg, + #8b5cf6 0%, + #d946ef var(--fill, 0%), + rgba(255, 255, 255, 0.1) var(--fill, 0%), + rgba(255, 255, 255, 0.1) 100% + ); + } + + .range:focus-visible { + outline: 2px solid rgba(167, 139, 250, 0.8); + outline-offset: 4px; + } + + .range::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + height: 16px; + width: 16px; + border-radius: 9999px; + background: #f5f3ff; + border: 2px solid #7c3aed; + box-shadow: 0 0 14px -2px rgba(168, 85, 247, 0.9); + cursor: grab; + } + + .range::-webkit-slider-thumb:active { + cursor: grabbing; + } + + .range::-moz-range-thumb { + height: 14px; + width: 14px; + border-radius: 9999px; + background: #f5f3ff; + border: 2px solid #7c3aed; + box-shadow: 0 0 14px -2px rgba(168, 85, 247, 0.9); + cursor: grab; + } + + .range::-moz-range-track { + background: transparent; + } } diff --git a/src/app/page.tsx b/src/app/page.tsx index ad84d08..f6e35aa 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -63,7 +63,9 @@ export default async function DashboardPage() { diff --git a/src/components/ProjectDialog.tsx b/src/components/ProjectDialog.tsx index fc5d915..994d5e1 100644 --- a/src/components/ProjectDialog.tsx +++ b/src/components/ProjectDialog.tsx @@ -287,7 +287,8 @@ export function ProjectDialog({ open, onClose, connections, project }: ProjectDi step={5} value={form.progress} onChange={(event) => update("progress", Number(event.target.value))} - className="w-full accent-violet-500" + className="range" + style={{ "--fill": `${form.progress}%` } as React.CSSProperties} /> diff --git a/src/components/ProjectHeader.tsx b/src/components/ProjectHeader.tsx index a390aa6..41d31e8 100644 --- a/src/components/ProjectHeader.tsx +++ b/src/components/ProjectHeader.tsx @@ -193,27 +193,22 @@ export function ProjectHeader({ Fortschritt {progress}% -
-
-
-
- setProgress(Number(event.target.value))} - onMouseUp={() => patch({ progress })} - onTouchEnd={() => patch({ progress })} - onKeyUp={() => patch({ progress })} - aria-label="Fortschritt anpassen" - className="absolute inset-0 h-2 w-full cursor-pointer opacity-0" - /> -
+ {/* Eigener Regler statt eines unsichtbaren Eingabefelds ueber einem + gezeichneten Balken: so gibt es einen sichtbaren Griff. */} + setProgress(Number(event.target.value))} + onMouseUp={() => patch({ progress })} + onTouchEnd={() => patch({ progress })} + onKeyUp={() => patch({ progress })} + aria-label="Fortschritt anpassen" + className="range" + style={{ "--fill": `${progress}%` } as React.CSSProperties} + />
window.innerWidth - margin) left = rect.right - width; left = Math.min(Math.max(margin, left), window.innerWidth - width - margin); const panelHeight = panelRef.current?.offsetHeight ?? 0;