# 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
<Application.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <ResourceInclude Source="avares://YourApp/Design/Tokens.axaml" />
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Application.Resources>

<Application.Styles>
  <FluentTheme />
  <StyleInclude Source="avares://YourApp/Design/IslandStyles.axaml" />
</Application.Styles>
```

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<string> Tags;
    List<SubTask> 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<LogLine> 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.
