diff --git a/src/ClaudeDo.Ui/CLAUDE.md b/src/ClaudeDo.Ui/CLAUDE.md index da6cea26..fb2f5549 100644 --- a/src/ClaudeDo.Ui/CLAUDE.md +++ b/src/ClaudeDo.Ui/CLAUDE.md @@ -31,8 +31,8 @@ ViewModels/ Conflicts/ — ConflictResolverViewModel + ConflictModels Views/ — mirrors the VM layout; Islands/Detail/ holds TaskHeaderBar, DescriptionStepsCard, WorkConsole; plus SessionTerminalView -Views/Controls/ — MarkdownView, ModalShell, ThemedDatePicker, DiffTextView, InheritedBadge, - AgentConfigEditor, UsagePill, UsageGaugeBar +Views/Controls/ — MarkdownView, ModalShell, ThemedDatePicker, DiffTextView, DiffEditorSetup, + InheritedBadge, AgentConfigEditor, UsagePill, UsageGaugeBar Design/ — Tokens.axaml (design tokens; merged before styles) + IslandStyles.axaml (component styles + the filled icon geometry library) ``` @@ -76,6 +76,12 @@ split/wrap toggles persist to `ui.config.json` via `AppSettings`. single-task and planning unit-merge conflicts. Full detail → [review-merge](../../docs/explore-notes/review-merge.md). +The two surfaces are **not** variants of one control (read-only 2-way renderer over aligned rows +vs. 3-way editor over a writable document), but they share their AvaloniaEdit host plumbing via +`Views/Controls/DiffEditorSetup.cs`: the process-wide TextMate `Registry`, `InstallHighlighting`, +`ApplyGrammar`, the `Brush` resource fallback, the `Seg` segment, and `VerticalScrollSync`. Put +new editor boilerplate there rather than copying it a third time. + ## Services - **WorkerClient / IWorkerClient** — SignalR client on `http://127.0.0.1:47821/hub`, auto-reconnect with exponential backoff. The surface **tracks `WorkerHub`** — treat `src/ClaudeDo.Worker/Hub/WorkerHub.cs` as the canonical method list rather than duplicating it here. Events mirror `HubBroadcaster`. Lifecycle (`StartAsync`/`StopAsync`) and a few admin methods live only on the concrete `WorkerClient`. @@ -96,6 +102,11 @@ uppercase. Modals use `TaskCompletionSource` results behind the reusable `ModalShell` control — the dialog sets the result on save/cancel, the caller awaits the TCS. +`ModalShell` also owns the window chrome for every modal: the titlebar drag goes through +`Window.BeginMoveDrag` (so Windows snap works — drag to the top edge to maximise; the OS only +snaps `CanResize="True"` windows, which is the opt-in), and it insets itself by the window's +`OffScreenMargin` so a maximised extended-client-area window isn't clipped at the edges. + ## Gotchas - **`PathIcon` *fills* its geometry.** Line-art/stroke icons must be authored as filled geometry or rendered with a stroked `Path` (e.g. `Icon.PlanDay` via the `Path.plan-icon` style). A pure stroke path in a `PathIcon` is **invisible**.