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) <noreply@anthropic.com>
This commit is contained in:
@@ -69,6 +69,8 @@ export async function POST(request: Request) {
|
|||||||
email: email ?? null,
|
email: email ?? null,
|
||||||
passwordHash: await hashPassword(password),
|
passwordHash: await hashPassword(password),
|
||||||
role: "USER",
|
role: "USER",
|
||||||
|
// Die Registrierung meldet direkt an.
|
||||||
|
lastLoginAt: new Date(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ export async function POST(request: Request) {
|
|||||||
email: email ?? null,
|
email: email ?? null,
|
||||||
passwordHash: await hashPassword(password),
|
passwordHash: await hashPassword(password),
|
||||||
role: "ADMIN",
|
role: "ADMIN",
|
||||||
|
// Die Einrichtung meldet direkt an – sonst stuende im Adminbereich
|
||||||
|
// "noch nie angemeldet", obwohl gerade eine Sitzung laeuft.
|
||||||
|
lastLoginAt: new Date(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+60
-1
@@ -79,7 +79,9 @@
|
|||||||
* Weichzeichnung wirkungslos.
|
* Weichzeichnung wirkungslos.
|
||||||
*/
|
*/
|
||||||
.popover {
|
.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: 1px solid rgba(255, 255, 255, 0.11);
|
||||||
border-radius: 0.9rem;
|
border-radius: 0.9rem;
|
||||||
box-shadow:
|
box-shadow:
|
||||||
@@ -208,4 +210,61 @@
|
|||||||
background: #0a0c1a;
|
background: #0a0c1a;
|
||||||
color: #e6e8f5;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -63,7 +63,9 @@ export default async function DashboardPage() {
|
|||||||
<StatCard
|
<StatCard
|
||||||
label="Ideen"
|
label="Ideen"
|
||||||
value={ideas}
|
value={ideas}
|
||||||
hint={STATUS_META.IDEA.description}
|
// Kurzer Hinweis statt der langen Statusbeschreibung – die wurde in
|
||||||
|
// der schmalen Kachel mitten im Wort abgeschnitten.
|
||||||
|
hint="Noch nichts gebaut"
|
||||||
icon={Lightbulb}
|
icon={Lightbulb}
|
||||||
color={STATUS_META.IDEA.color}
|
color={STATUS_META.IDEA.color}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -287,7 +287,8 @@ export function ProjectDialog({ open, onClose, connections, project }: ProjectDi
|
|||||||
step={5}
|
step={5}
|
||||||
value={form.progress}
|
value={form.progress}
|
||||||
onChange={(event) => update("progress", Number(event.target.value))}
|
onChange={(event) => update("progress", Number(event.target.value))}
|
||||||
className="w-full accent-violet-500"
|
className="range"
|
||||||
|
style={{ "--fill": `${form.progress}%` } as React.CSSProperties}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -193,13 +193,8 @@ export function ProjectHeader({
|
|||||||
<span>Fortschritt</span>
|
<span>Fortschritt</span>
|
||||||
<span className="tabular-nums text-slate-300">{progress}%</span>
|
<span className="tabular-nums text-slate-300">{progress}%</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative">
|
{/* Eigener Regler statt eines unsichtbaren Eingabefelds ueber einem
|
||||||
<div className="h-2 w-full overflow-hidden rounded-full bg-white/6">
|
gezeichneten Balken: so gibt es einen sichtbaren Griff. */}
|
||||||
<div
|
|
||||||
className="accent-bar h-full rounded-full transition-[width] duration-300"
|
|
||||||
style={{ width: `${Math.max(1, progress)}%` }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min={0}
|
min={0}
|
||||||
@@ -211,10 +206,10 @@ export function ProjectHeader({
|
|||||||
onTouchEnd={() => patch({ progress })}
|
onTouchEnd={() => patch({ progress })}
|
||||||
onKeyUp={() => patch({ progress })}
|
onKeyUp={() => patch({ progress })}
|
||||||
aria-label="Fortschritt anpassen"
|
aria-label="Fortschritt anpassen"
|
||||||
className="absolute inset-0 h-2 w-full cursor-pointer opacity-0"
|
className="range"
|
||||||
|
style={{ "--fill": `${progress}%` } as React.CSSProperties}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<ProjectDialog
|
<ProjectDialog
|
||||||
open={editOpen}
|
open={editOpen}
|
||||||
|
|||||||
@@ -56,7 +56,13 @@ export function Popover({
|
|||||||
const margin = 8;
|
const margin = 8;
|
||||||
const gap = 6;
|
const gap = 6;
|
||||||
|
|
||||||
|
// Bevorzugte Ausrichtung, bei Ueberlauf auf die andere Seite wechseln.
|
||||||
|
// Nur Festklemmen am Fensterrand waere schlecht: bei einem Ausloeser weit
|
||||||
|
// links stuende das Menue sonst quer ueber der Seite statt an seinem
|
||||||
|
// Ausloeser.
|
||||||
let left = align === "end" ? rect.right - width : rect.left;
|
let left = align === "end" ? rect.right - width : rect.left;
|
||||||
|
if (left < margin) left = rect.left;
|
||||||
|
if (left + width > window.innerWidth - margin) left = rect.right - width;
|
||||||
left = Math.min(Math.max(margin, left), window.innerWidth - width - margin);
|
left = Math.min(Math.max(margin, left), window.innerWidth - width - margin);
|
||||||
|
|
||||||
const panelHeight = panelRef.current?.offsetHeight ?? 0;
|
const panelHeight = panelRef.current?.offsetHeight ?? 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user