Files
ClaudeDo/docs/superpowers/specs/2026-08-20-ux-struktur-design.md
T

13 KiB
Raw Blame History

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.