Polish: A11y-, Motion- & Deep-Linking-Sweep (Web Interface Guidelines)
Aus dem web-design-guidelines-Audit über das ganze Frontend: P1 — index.css: prefers-reduced-motion-Block (Animationen/Transitions aus), color-scheme dark/light, zwei `transition: all` → explizite Properties, globaler :focus-visible-Ring. Formular-aria-labels (SystemDrawer-Passwörter inkl. name/autocomplete/spellCheck, Memory, Connect, ModelBrowse, LaneEditor, CustomDialog). Icon-Button-aria-labels + dekorative Icons aria-hidden. P2 — Memory-Lösch-Bestätigung (war sofort), overscroll-behavior:contain auf Modals (CustomDialog/Agent/Cockpit/CommandPalette), ModelBrowse fmtN → Intl.NumberFormat. P3 — Deep-Linking: top-level View im URL-Hash (#models), Reload/Teilen/Cmd-Klick funktionieren; Sidebar-Nav als <a href="#id"> (echte Links, aria-current), hashchange-Sync; index.css-Aktiv-Selektoren button→a nachgezogen. Verifiziert: npm run build (tsc strict) clean; live gegen die Box (Hash-Nav, Reload-Persistenz, aria-current, Aktiv-Styling teal+Akzent, keine Konsolenfehler). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -94,9 +94,11 @@ export function MemoryView() {
|
||||
setContent(""); setShowAdd(false); reloadMemory()
|
||||
}
|
||||
|
||||
async function del(id: string) {
|
||||
await api(`/api/memory/${id}`, { method: "DELETE" })
|
||||
reloadMemory()
|
||||
function del(id: string) {
|
||||
showConfirm("Eintrag löschen?", "Diesen Gedächtnis-Eintrag dauerhaft entfernen?", async () => {
|
||||
try { await api(`/api/memory/${id}`, { method: "DELETE" }); reloadMemory() }
|
||||
catch (e: any) { showAlert("Fehler", `Löschen fehlgeschlagen: ${e.message || e}`) }
|
||||
})
|
||||
}
|
||||
|
||||
async function copyPrompt() {
|
||||
@@ -156,6 +158,8 @@ export function MemoryView() {
|
||||
<input
|
||||
value={q}
|
||||
onChange={(e) => setQ(e.target.value)}
|
||||
aria-label="Gedächtnis durchsuchen"
|
||||
type="search"
|
||||
placeholder="Semantisch suchen…"
|
||||
className="w-52 h-9 pl-8 pr-3 rounded-lg border border-border/60 bg-card/45 text-xs outline-none focus:ring-1 focus:ring-primary/50 text-foreground"
|
||||
/>
|
||||
@@ -176,8 +180,8 @@ export function MemoryView() {
|
||||
</div>
|
||||
<button onClick={cleanup} disabled={deduping}
|
||||
className="flex h-9 w-9 items-center justify-center rounded-lg border border-border/60 bg-card hover:border-primary/50 transition-all cursor-pointer shadow-md disabled:opacity-50"
|
||||
title="Deduplizieren">
|
||||
<Sparkles className="h-4 w-4 text-primary" />
|
||||
aria-label="Duplikate bereinigen" title="Deduplizieren">
|
||||
<Sparkles className="h-4 w-4 text-primary" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -200,13 +204,15 @@ export function MemoryView() {
|
||||
<div className="rounded-2xl border border-border/60 bg-card/45 backdrop-blur-md p-4 space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="text-xs font-bold uppercase tracking-wider text-muted-foreground">Neuen Eintrag anlegen</div>
|
||||
<button onClick={() => setShowAdd(false)} className="text-muted-foreground hover:text-foreground"><X className="h-4 w-4" /></button>
|
||||
<button onClick={() => setShowAdd(false)} aria-label="Schließen" className="text-muted-foreground hover:text-foreground"><X className="h-4 w-4" aria-hidden="true" /></button>
|
||||
</div>
|
||||
<textarea value={content} onChange={(e) => setContent(e.target.value)} rows={2}
|
||||
aria-label="Eintragstext"
|
||||
placeholder="Eine Regel, Vorliebe oder einen stabilen Fakt über dich oder das Projekt…"
|
||||
className="w-full resize-none rounded-xl border border-border/60 bg-background/30 p-3 text-xs outline-none focus:ring-1 focus:ring-primary/50 text-foreground leading-relaxed" />
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<select value={category} onChange={(e) => setCategory(e.target.value)}
|
||||
aria-label="Kategorie"
|
||||
className="h-8 rounded-lg border border-border/60 bg-background/50 px-2 text-xs outline-none font-semibold text-foreground cursor-pointer">
|
||||
{CATEGORIES.map((c) => <option key={c} value={c} className="bg-popover text-foreground">{CAT_CONFIG[c]?.label || c}</option>)}
|
||||
</select>
|
||||
@@ -321,9 +327,9 @@ export function MemoryView() {
|
||||
title={isAuto ? "Automatisch gelernt" : "Manuell angelegt"}>
|
||||
{isAuto && <Sparkles className="h-2.5 w-2.5" />}{m.source}
|
||||
</span>
|
||||
<button onClick={() => del(m.id)} title="Eintrag löschen"
|
||||
<button onClick={() => del(m.id)} aria-label="Eintrag löschen" title="Eintrag löschen"
|
||||
className="h-7 w-7 rounded-lg flex items-center justify-center border border-border/40 text-muted-foreground hover:text-red-400 hover:bg-red-500/5 transition-all opacity-0 group-hover:opacity-100">
|
||||
<Trash2 className="h-3.5 w-3.5" />
|
||||
<Trash2 className="h-3.5 w-3.5" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user