# 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`, `DetailsIslandViewModel` und 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.json` **und** `locales/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 `WorkingDir` hat**. Neue Property `HasNoLinkedRepo` am `ListsIslandViewModel`, 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 und `Menü → 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: 1. Banner → *Repo importieren* 2. Task-Liste leer, Liste **ohne** Repo (#192) → *Diese Liste hat kein Repo; in den List-Settings verknüpfen* 3. Task-Liste leer, Liste **mit** Repo (#192) → *Task anlegen, dann Rechtsklick → „Send to queue" — Claude arbeitet ihn in einem eigenen Worktree ab* 4. Review-Stufe: am Approve-Gate-Hinweis (den #190 in `WorkConsole.axaml` baut) **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.