# ClaudeDo — Avalonia Handoff ## Overview ClaudeDo is an agent dispatcher for Claude Code: a Windows desktop app that presents background coding agents as tasks. Each task has a title, a list, a git worktree/branch, an agent status (idle / queued / running / review / error), a live session log, and a diff. The UI is organised as **three floating islands** (Lists / Tasks / Details) over a dark "sea" background, Windows-11 style. The bundled HTML file is a **design reference**, not production code. Your job is to recreate it as a native Avalonia app — match the look, feel, and interaction model, but use idiomatic AXAML, Avalonia controls, and whatever MVVM / ReactiveUI / CommunityToolkit patterns your codebase already uses. ## Fidelity **High-fidelity.** All colors, typography, spacing, corner radii, shadows, and interaction states are final. Recreate pixel-perfectly using Avalonia primitives. The one exception: motion — CSS animations translate approximately to Avalonia `Transitions` / `Animation`; the durations and easings in `Tokens.axaml` are the intent. ## What's in this package | File | Purpose | |---|---| | `Tokens.axaml` | `ResourceDictionary` — colors, brushes, spacing, corner radii, typography, shadows, motion durations. **Merge this first in `App.axaml`.** | | `IslandStyles.axaml` | `Styles` — classed styles for Island, Chip, Button, TextBox, TaskRow, AgentStrip, Terminal, ListItem. Depends on `Tokens.axaml`. | | `ClaudeDo.html` | The live design reference — open it in a browser to see behavior, hover states, animations, modals. | | `ClaudeDo-standalone.html` | Fully offline single-file version (no network). Ship this with the handoff. | | `app.jsx`, `islands.jsx`, `modals.jsx`, `icons.jsx`, `data.jsx`, `styles.css` | Source of the reference. Read `styles.css` for any measurement you need to verify; read the JSX for component structure and state transitions. | | `ComponentSpec.md` | This file section below — maps every visual element to the AXAML control you should use. | ## How to wire the tokens In `App.axaml`: ```xml ``` Pack **Inter Tight** (sans) and **JetBrains Mono** (mono) as embedded resources and reference them via `avares://YourApp/Assets/Fonts/#Inter Tight` in `Tokens.axaml` if the system-font fallback isn't good enough. --- ## Window chrome The reference shows a Windows-11-style app in a chromeless window with a custom title bar and taskbar. For a native Avalonia app, use `SystemDecorations="None"` + `ExtendClientAreaToDecorationsHint="True"` and draw your own title bar, OR use the platform chrome — the islands-over-sea metaphor works either way. The taskbar strip at the bottom of the reference is decorative; drop it. ## Layout Root window: ``` ┌─────────────────────────────────────────────────────────┐ │ TitleBar │ ├─────────────┬──────────────────────────┬────────────────┤ │ Lists │ Tasks │ Details │ │ (260px) │ (1fr, min 340px) │ (320px) │ │ │ │ hides <1100px │ └─────────────┴──────────────────────────┴────────────────┘ ``` Use a `Grid` with 3 columns: `260,*,320`. Collapse the Details column when `ActualWidth < 1100` via a bound `ColumnDefinition.Width`. Between columns and around the grid, add 14px gap — put each island in a `Border Classes="island"` with `Margin="7"` so you get the island-to-island gap naturally. Background of the grid cell: apply `DesktopBackgroundBrush` from tokens, plus a subtle radial-gradient overlay via a `Border` with an opacity mask if desired. --- ## Components ### Island (base container) - `Border Classes="island"` - Contents: header section + scrollable body - Header: inner `Border Classes="island-header"` with an eyebrow label (mono, uppercase, tracking 1.4) and a title - Body: `ScrollViewer` → `StackPanel` or `ItemsControl` - All three columns are islands. ### Lists island (left) - Search box: `TextBox Classes="search"` with left-aligned search icon (PathIcon) - Nav items: `ItemsControl` bound to a `Lists` collection - Each item is `Border Classes="list-item"` (toggle `active` class when selected) containing - `PathIcon` (16px) - `TextBlock` (list name, 13px) - `TextBlock` (count, mono 10px, right-aligned, TextFaintBrush) - Lists shown: My Day, Important, Planned, Running, Review, Tasks (by project name) ### Tasks island (middle) Header row: - Eyebrow: weekday date ("MONDAY · APR 28") - Title: "My Day" (or current list name) — 24px semibold - Subtitle: "{N} open · {N} running · {N} in review" — mono 11px TextMute - Right side: icon buttons (sort, filter, show-completed toggle) Add-task row: - `TextBox` with placeholder "Add a task…" - On Enter: dispatch new task (see ViewModel spec) Task list: - `ItemsControl` → `Border Classes="task-row"` per task - Row content: `Grid` with columns `Auto,*,Auto` - Left: `Ellipse Classes="task-check"` (toggles `done` class on completion) — use a `Button` with a templated Ellipse for keyboard support - Middle: `StackPanel` vertical - Title: `TextBlock` 14px, strike-through when done - Meta row: `StackPanel` horizontal with 8px gap, children: - `Border Classes="chip {status}"` (status chip — Running / Review / Error / Queued / Idle) - `Border Classes="chip"` with list name - `Border Classes="chip"` with mono branch name (e.g. `agent/auth-pool`) - `Border Classes="chip"` with diff stats (`+142 −86`) - Live tail of latest agent output when running — use `TextTrimming="CharacterEllipsis"` in a fixed-width container - Right: `Button Classes="icon-btn"` (star) - Selection: toggle `selected` class; add a `Rectangle` with `Width=2` as the left accent bar (child of the task-row Border) ### Details island (right) Shown when a task is selected. Sections, top to bottom: 1. **Header**: task title (editable — `TextBox` with no visible border, `FontSize=18`), list chip, delete icon button 2. **Agent strip** — `Border Classes="agent-strip {status}"`: - Row 1: status indicator dot + status label ("Running" / "Review" / etc.) + model name ("claude-sonnet-4.5") + turns + tokens + elapsed - Row 2: Worktree path (mono, truncating) - Row 3: Branch → Base ("agent/auth-pool ← main") + commit count + diff stats - Buttons: "Open diff" / "Worktree" / "Stop" (when running) / "Approve & merge" (when review) 3. **Session output** — `Border Classes="terminal"` with a `ScrollViewer` auto-scrolled to bottom: - Each line is a `TextBlock Classes="log-{kind}"` — kinds: sys, tool, claude, stdout, stderr, done, msg - Below it, a prompt input: `[you]` prefix + `TextBox` to send messages to the agent 4. **Subtasks** — `ItemsControl` of checkbox + text rows 5. **Notes** — multi-line `TextBox`, `AcceptsReturn="True"` 6. **Metadata** — created date, last activity, tags (readonly chips) ### Modals Two modals in the reference: **Diff** and **Worktree**. Use `Window` with `WindowStartupLocation="CenterOwner"` and a scrim (`Border` over the main window with `Background="#BF030504"` + blur via `OpacityMask` or a child `Grid`). Or use `Dialog` if your shell has one. **Diff modal**: left sidebar of files (each with `+N −N` stats), right pane with syntax-colored hunks. Use two `ListBox`-style panels side-by-side. For lines: `del` = red tinted, `add` = green tinted, `ctx` = neutral. Left gutter columns: old line number, new line number, sign (`+` / `−` / space). **Worktree modal**: folder tree with `M` (modified) / `A` (added) badges. `TreeView` fits naturally. ### Status mapping | Status | Chip color | Icon | When | |---|---|---|---| | idle | TextMute | circle | Task created, agent not dispatched | | queued | Sage | dots | Agent queued behind others | | running | Accent (moss) | pulse dot | Agent actively working | | review | Peat | eye | Agent finished; awaiting approval | | error | Blood | exclamation | Agent failed | --- ## State & interactions ### Task model (MVVM) ```csharp public class TaskItem : ReactiveObject { string Id, Title, List; bool Done, Starred, MyDay; DateTime? Due, Created; string Notes; List Tags; List Subtasks; AgentState Agent; // null if not dispatched } public class AgentState : ReactiveObject { AgentStatus Status; // Idle | Queued | Running | Review | Error string Model, Worktree, Branch, BaseBranch; int Commits, Turns, Tokens; DiffStats Diff; // Files, Additions, Deletions DateTime? StartedAt, FinishedAt; ObservableCollection Log; } ``` ### Key interactions - **Toggle done**: click checkbox → flip `Done`, animate strike-through (0.2s ease-out) - **Select task**: click row → set `SelectedTask`; details island rebinds - **Add task**: Enter in the add-task textbox → prepend new task; scroll list to top; 0.3s fade-in animation on the new row (use `Animation` with opacity + `TranslateTransform.Y`) - **Dispatch agent**: "Start agent" button in Details → sets `Agent.Status = Running`, appends sys log "Agent dispatched." - **Stop agent**: → `Status = Review` (or `Error` on failure), appends sys log - **Send prompt**: Enter in prompt input → append `[you] {msg}` to log - **Open diff / worktree**: opens modal; Esc closes ### Keyboard - `/` focuses the search box in the Lists island - `Cmd/Ctrl+N` focuses add-task - `Space` toggles done on selected row - `Esc` closes any open modal ### Animations - Task-row hover: background transition 0.1s - Task-row add: 0.3s opacity + slight Y-slide - Task-row complete: 0.25s strike-through + fade to `done` styling - Running status dot: infinite pulse (opacity 0.4 → 1.0, 1.2s) - Modal open: 0.18s opacity + scale (0.98 → 1.0) - Backdrop: 0.15s opacity fade ### Responsive - `< 1100px`: hide Details island; details open as a transient panel or modal on task select - `< 780px`: hide Lists island; use a hamburger drawer --- ## Design tokens (reference) All final values live in `Tokens.axaml`. Reproduced here for reading: **Surfaces**: `#0A0E0C` void · `#0D1311` deep · `#161D1A` surface · `#1C2422` surface-2 · `#222B28` surface-3 · `#2A3330` line **Text**: `#E4EBE4` primary · `#9AA8A0` dim · `#6B7973` mute · `#4A5550` faint **Accents**: `#7C9166` moss (primary) · `#8B9D7A` sage · `#D4A574` peat · `#C87060` blood **Spacing**: 4, 8, 12, 14 (island gap), 18, 24 **Corner radii**: 14 (island) · 12 (modal) · 10 (chip) · 8 (task row, input) · 6 (button) · 999 (pill) **Typography**: Inter Tight (sans), JetBrains Mono (mono). Scale: 10 (eyebrow) / 11 (mono, micro) / 13 (body) / 14 (task title) / 18 (h3) / 24 (h2) / 32 (h1) **Shadows**: - Island: `0 20 40 #59000000, 0 2 4 #4D000000` - Modal: `0 40 80 #B2000000` **Motion**: 120ms (fast) / 180ms (base) / 300ms (slow). Easing: cubic-bezier(0.4, 0, 0.2, 1) — use Avalonia's `CubicEaseOut` or a custom `SplineEasing`. --- ## Acceptance checklist - [ ] Three-island layout with correct spacing and grid collapse at <1100px - [ ] Lists sidebar with icons, counts, search, active state - [ ] Task rows with checkbox, title, meta chips (status/list/branch/diff), star - [ ] Task selection updates Details island - [ ] Agent strip shows status, model, turns, tokens, elapsed, worktree, branch - [ ] Session terminal renders all log kinds with distinct colors, auto-scrolls, accepts prompt input - [ ] Diff modal with file sidebar and tinted add/del lines - [ ] Worktree modal with M/A badges - [ ] Status chip tints match the spec - [ ] Fonts: Inter Tight + JetBrains Mono packed and applied - [ ] Motion: task add/toggle, running pulse, modal open, hover transitions - [ ] Keyboard shortcuts wired ## Questions / contact The HTML reference is the source of truth for any visual ambiguity. Open `ClaudeDo-standalone.html` and inspect directly.