13 KiB
UX-Struktur: Kontextmenü, Settings, Task-Zeile, Erststart — Design
Stand: 2026-08-20 · Codestand f9a8ed7 · Freigegeben von Mika im Brainstorming
Die vier strukturellen Themen aus dem UX-Audit vom 2026-08-20. Die mechanischen Befunde desselben Audits laufen bereits als Tasks #189 (Silent No-Ops → Footer-Fehler), #190 (Precondition-Hinweise), #191 (Aktions-/Bestätigungs-Konsistenz), #192 (Empty States). Dieses Design setzt auf deren Ergebnis auf und wiederholt es nicht.
Was hier nicht drinsteht: die Audit-Befunde selbst (Memory ux_audit_2026_08_20.md) und die
Mechanik von Review/Merge (docs/explore-notes/review-merge.md).
Gemeinsame Randbedingungen
- Alle drei Umsetzungs-Tasks laufen nach #192. Sie fassen dieselben Views an, und #189–#192
ändern Locale-Dateien,
TaskRowView.axaml.cs,DetailsIslandViewModelund die Empty-State-Keys. - Keine Funktion verschwindet still. Wo etwas aus einer Oberfläche verschwindet, muss dieses Design sagen, wo es stattdessen erreichbar ist — und der Task muss das belegen.
- Neue Texte immer als Keys in
locales/en.jsonundlocales/de.json(Localization.Tests erzwingt Parity). - Visuelle Verifikation macht Mika. Jeder Task markiert sie im Abschlussbericht als offen.
1. Task-Kontextmenü restrukturieren
Problem. TaskRowView.axaml.cs baut ~18 flache MenuItems mit vier Separatoren. Kernaktionen
(Queue rein/raus, Abbrechen) stehen visuell gleichwertig neben Planning-Session-Lifecycle und
My-Day-Verwaltung. Zusätzlich werden Einträge bei nicht erfüllter Bedingung komplett ausgeblendet
— das Menü hat je Zustand ein anderes Layout, und der User erfährt nie, dass eine Aktion
existiert.
Entscheidung: gruppieren und verschachteln. Das Menü bleibt die vollständige Action-Surface für einen Task (keine Verlagerung ins Detail-Pane — das ist selbst schon dicht).
Send to queue [disabled + Grund]
Remove from queue [disabled + Grund]
Cancel execution [disabled + Grund]
Open quick session [disabled + Grund]
Refine task [disabled + Grund] ← neu (siehe Thema 3)
─────────────────────────────
Mark as ▸ Done · Cancelled · ─ · Mark manual / Mark as Claude task
Planning ▸ Open · Resume · Finalize · Discard
Schedule ▸ Schedule for… · Clear schedule · ─ · Add to My Day / Remove from My Day
─────────────────────────────
Delete task… (aus #191, bleibt unten abgesetzt)
Sichtbarkeitsregeln.
| Ebene | Regel |
|---|---|
| Gruppe 1 (5 Einträge) | Immer sichtbar, Position fix. Bedingung nicht erfüllt → IsEnabled=false + Grund. |
| Untermenü-Einträge | Heutige Ausblende-Logik bleibt — die Auswahl ist dort exklusiv (Manual ⇄ Claude-Task, Add ⇄ Remove My Day). |
| Untermenü-Kopf | IsEnabled=false, wenn er leer wäre (z.B. „Planning" auf einem Manual-Task). |
| Delete | Wie #191 es baut, nur eigene Gruppe unten. |
Grund-Anzeige. Primär ToolTip.Tip am disabled MenuItem. Verifikationspflicht: Der Task
muss headless prüfen, ob Avalonia 12 Tooltips auf IsEnabled=false MenuItems überhaupt anzeigt.
Wenn nicht → Grund als Suffix im Header ("Send to queue — kein Repo verknüpft"). Kein
stillschweigendes Weglassen; wenn beides nicht geht, muss der Task es als Befund melden.
Wo die Gründe herkommen. Neue berechnete Properties auf TaskRowViewModel neben den
bestehenden CanX, z.B. SendToQueueDisabledReason, CancelDisabledReason,
QuickSessionDisabledReason, RefineDisabledReason, PlanningDisabledReason (jeweils string?,
null = kein Grund nötig). Keine Bedingungslogik in der View.
Struktur im Code. Das Menü wird weiterhin erst beim Öffnen gebaut (kein Rendering-Overhead
pro Zeile). MakeItem bekommt einen optionalen reason-Parameter und schaltet auf IsEnabled
statt IsVisible um, wenn der Aufrufer das verlangt.
Ergebnis: 18 flache Einträge → 9 Top-Level-Zeilen, davon 5 mit fixer Position.
2. Settings-Modal entzerren
Problem. Der General-Tab mischt 10+ Konzeptgruppen (Sprache, Accent, Default-Instructions, Model, Permission, Model-Presets-Tabelle, MaxTurns-Ceiling, Parallelität, Usage-Gate-Prozente, Report-Excluded-Paths, Standup-Wochentag, Session-Skills-Checkboxen). Session Skills stehen doppelt (Auswahl in General, Verwaltung im Skills-Tab). Und die sechs Tabs füllen den 580 px breiten TabStrip bereits aus — ein siebter passt nicht.
Entscheidung: Sidebar-Navigation mit zwei Gruppen.
┌ Einstellungen ─────────────────────────────────────────┐
│ BASIS │ [Panel der gewählten Kategorie] │
│ Allgemein │ │
│ Ausführung │ │
│ Prime Claude │ │
│ │ │
│ ERWEITERT │ │
│ Worktrees │ │
│ Dateien & Prompts │ │
│ Session Skills │ │
│ Berichte │ │
│ Online Inbox │ (nur wenn ShowOnlineInbox) │
└────────────────────┴───────────────────────────────────┘
[Abbrechen] [Speichern]
Kategorien-Inhalt.
| Kategorie | Inhalt | Herkunft |
|---|---|---|
| Allgemein | Sprache, Accent-Preset, Default-Claude-Instructions | General |
| Ausführung | Default-Model, Permission-Mode, Model-Presets-Tabelle, MaxTurns-Ceiling, Max parallele Ausführungen, Usage-Gate (5h/7d %) | General |
| Prime Claude | Schedules + Daily-Prep-Max-Tasks | unverändert |
| Worktrees | Strategie, Root, Auto-Cleanup, Cleanup-/Reset-Aktionen | unverändert |
| Dateien & Prompts | Agents-Restore, Prompt-Pfade, Customized-Prompts | unverändert (Files) |
| Session Skills | zusammengelegt: je installierter Skill eine Zeile mit Checkbox (global aktiv) + Update/Remove; darunter Install-URL | Skills-Tab + Checkbox-Liste aus General |
| Berichte | Standup-Wochentag, Report-Excluded-Paths | General (neu herausgelöst) |
| Online Inbox | unverändert, weiter an ShowOnlineInbox gekoppelt |
unverändert |
Session-Skills-Zusammenlegung. Die Checkbox-Liste im General-Tab entfällt. Beide VMs
(GeneralSettingsTabViewModel.SessionSkills, SessionSkillsSettingsTabViewModel) speisen künftig
eine Liste; die Auswahl (global aktive Skills) wird weiterhin über denselben Pfad gespeichert
wie heute. Der Task muss belegen, dass Speichern/Laden der Auswahl unverändert funktioniert —
das ist die einzige Stelle mit echtem Regressionsrisiko.
Repo-Hinweis statt Verstecken. Nichts wird ausgeblendet (verschwindende Einstellungen
irritieren in einem Power-Tool mehr als Dichte). Stattdessen zeigen Worktrees, Prime Claude,
Session Skills und Berichte oben einen Hinweisstreifen, solange keine Liste ein WorkingDir
hat: „Wirkt erst mit verknüpftem Repo" + Link, der den Repo-Import öffnet. Dafür eine neue
Property HasLinkedRepo am SettingsModalViewModel.
Umsetzung risikoarm. Das TabControl bleibt als Content-Host: nur der TabStrip wird
ausgeblendet, und eine Sidebar-ListBox bindet SelectedIndex. Die vorhandenen Panel-Inhalte
wandern damit nahezu unverändert mit (General wird gesplittet, Skills gemerged, Berichte neu).
Keine Neuschrift der 556 AXAML-Zeilen, compiled bindings bleiben intakt. Sidebar-Modell:
SettingsCategory(Key, Label, Group, IsVisible, RequiresRepo) in SettingsModalViewModel.Categories.
Fensterbreite 580 → 700.
3. TaskRow-Dichte
Problem. Eine Zeile kann 16 Elemente zeigen. Die Maximaldichte trifft real fast nur einen
WaitingForReview-Task in einer Smart-List (Status-, List-, Branch-, Diff-Chip plus Icons und
Buttons) — aber genau dort ist die Zeile am schwersten zu lesen.
Entscheidung: Zustand bleibt, Aktionen auf Hover-oder-Selektion, reine Metadaten raus.
| Klasse | Elemente |
|---|---|
| Immer sichtbar (Zustand) | Chevron (Planning-Parent), Done-Toggle, #Nummer, Titel, die vier Badges (DRAFT/PLANNED/Planning/MANUAL), Roadblock-Icon, Agent-Suggested-Icon, Status-Chip (bleibt tappbar → Mission Control), Diff-Chip, List-Chip (nur Smart-Lists, wie heute), Chain-Chip/Chain-Step-Badge, gesetzter Star |
| Hover ODER Selektion (Aktion) | Refine-Button, ungesetzter Star, Dequeue-X |
| Aus der Zeile raus | Branch-Chip |
Kein Funktionsverlust. Refine, Star und Dequeue bleiben über das Kontextmenü erreichbar — „Remove from queue" existiert dort, „Refine task" wird in Thema 1 neu ergänzt. Selektion als zweiter Trigger deckt Tastaturbedienung ab.
Ausnahme. Der Refine-Spinner (IsRefining) bleibt immer sichtbar. Ein laufender Refine
darf nicht verschwinden, wenn die Maus die Zeile verlässt.
Branch-Chip: Verlagerung, nicht Löschung. Der Branch-Name steht heute nirgends im
Detail-Pane (geprüft gegen DetailsIslandView.axaml und Views/Islands/Detail/*.axaml —
kein Treffer außer der Merge-Target-ComboBox). Er muss deshalb im selben Task in die
TaskHeaderBar als Meta-Zeile aufgenommen werden. WorkConsole.axaml fasst dieser Task
nicht an (Datei-Eigentum, siehe Plan).
Umsetzung. TaskRowViewModel bekommt IsHovered (gesetzt über PointerEntered/
PointerExited in TaskRowView.axaml.cs) und ein berechnetes
ShowRowActions => IsHovered || IsSelected. Die neuen Sichtbarkeiten sind AND-Verknüpfungen
mit den bestehenden CanRefine / CanRemoveFromQueue / IsStarred — keine bestehende Bedingung
wird ersetzt. Layout-Sprünge vermeiden: die Buttons behalten ihre Grid-Spalten
(Auto,Auto,32), es wechselt nur die Sichtbarkeit innerhalb fester Breite.
Ergebnis: Worst case ohne Hover 16 → 9 Elemente.
4. Erststart
Problem. Nach dem Seeding existieren nur My Day / Important / Planned und kein Repo. Es gibt kein Onboarding; die Empty States aus #192 beschreiben den Ist-Zustand, aber nicht die Reihenfolge Repo → Liste → Task → Queue → Review.
Entscheidung: kein Onboarding-Konstrukt. Ein zustandsgetriebenes Banner plus eine abgestimmte Textkette. Explizit kein Wizard, kein Willkommens-Modal, kein Onboarding-Zustand in DB oder Config.
Banner im Lists-Island direkt unter dem Header, optisch wie das bestehende Update-Banner des Shells (kein neues Stil-Vokabular):
┌──────────────────────────────────────────────┐
│ Noch kein Repo verknüpft. ClaudeDo führt │
│ Tasks in einem Git-Repo aus. │
│ [ Repo importieren ] │
└──────────────────────────────────────────────┘
- Sichtbar, solange keine User-Liste ein
WorkingDirhat. Neue PropertyHasNoLinkedRepoamListsIslandViewModel, neu berechnet beim Listen-Load und nach List-CRUD / List-Settings-Save. - Kein Dismiss, kein persistierter Zustand. Wer sein einziges Repo entfernt, bekommt den Weg zurück wieder gezeigt.
- Der Button ruft das vorhandene
OpenRepoImportCommand(dritter Einstieg neben dem Header-Button undMenü → Add repos).
Textkette. Die Stellen müssen als ein Weg lesbar sein. Die Keys aus #192 existieren zu diesem Zeitpunkt schon und werden nur nachgeschärft:
- Banner → Repo importieren
- Task-Liste leer, Liste ohne Repo (#192) → Diese Liste hat kein Repo; in den List-Settings verknüpfen
- Task-Liste leer, Liste mit Repo (#192) → Task anlegen, dann Rechtsklick → „Send to queue" — Claude arbeitet ihn in einem eigenen Worktree ab
- Review-Stufe: am Approve-Gate-Hinweis (den #190 in
WorkConsole.axamlbaut) eine Zeile ergänzen, die sagt, dass Approve gleichzeitig das Mergen ist.
Punkt 3 erklärt die Queue genau dort, wo der erste Task entsteht. Punkt 4 schließt die Lücke, dass der erste fertige Run in einem Zustand landet, den nichts ankündigt.
Nicht Teil dieses Designs
- Der WorkConsole-Git-Tab (laut Audit das dichteste Panel der App) — eigenes Thema.
- Mission Control und der Diff-Viewer.
- Alles, was #189–#192 schon abdecken.