Design: UX mockups for the /agents dashboard page (Penpot) #55

Closed
opened 2026-04-18 15:04:43 +00:00 by claude-desktop · 2 comments
Collaborator

User story

As a maintainer, I want visual mockups for the /agents page — list view, create/edit modal, delete-confirm, skill viewer + appendix editor, and empty/error states — produced in Penpot before the implementation ticket (A6) starts, so that the CRUD UI lands with a deliberate UX rather than being designed ad-hoc at implement-time.

Context

A6 (#53) scopes the functional requirements of the agents CRUD surface (endpoints, form fields, live state, cleanup-on-delete). This story covers the design layer upstream of it: layouts, component choices, interaction states, and copy. The operator (@charles) drives the Penpot session with the interactive Claude (claude-desktop) acting as UX designer via the Penpot MCP.

The existing dashboard lives in src/dashboard.html and has a minimal look. The mockups should extend that vocabulary — don't introduce a new design system, use what the dashboard already uses for colours, type scale, and spacing. If gaps exist (e.g. no modal or tag-input component today), propose the minimum-viable component extension and document it in the Penpot file.

Acceptance criteria

Penpot file

  • New Penpot page in the existing koinos team's primary file (or a new file named claude-hooks — dashboard, one-off decision at the start of the session) titled /agents.
  • Design frames produced at desktop width (min 1280 px) only. Mobile is out of scope — the admin surface is desktop-only.
  • Page deep-link pasted as a reference in this issue before it's closed.

Screens / states

  • List view — table of instances with columns: name, type, model (showing override with a badge when non-default), match_labels (chip list), queue depth, status (idle/busy/stopped pill). Sort + filter controls where they belong. Include a populated example (5–7 rows) plus an empty state ("No agents yet — create your first one").
  • Create modal — form fields: type dropdown, name input (with live-validation state — valid / duplicate / invalid chars), model dropdown, match_labels tag-input, prompt appendix textarea (with char count), notes textarea. Show primary / secondary action affordance.
  • Edit view — same form pre-filled. Visual distinction between create and edit flows (title, button label).
  • Delete-confirm modal — show what will be cleaned up (container name, worktree count, session count), a match_labels preview so the operator sees what routing they're breaking, and a "Also wipe volume" checkbox with a clear destructive-action visual. Confirm button disabled until the operator types the instance name.
  • Skill viewer + appendix editor — on the edit view, a section that lists skills (implement, review, address-review, rebase, merge, fix-ci, breakdown). Each skill is collapsible, read-only markdown render. Next to / below it: the per-agent prompt_appendix textarea with live character count. Visual distinction between the immutable base and the editable appendix.
  • Live-state indicators — a component spec for the idle/busy/stopped pill and the queue-depth chip, showing each state variant.
  • Error state — a container-down instance ("stopped" status). Include the visual for the row and any banner that surfaces the underlying error (e.g. "container exited 1 — see logs").

Interaction specs

  • For each screen, annotate the happy-path flow: what clicking each action does, where focus moves, what the loading state looks like.
  • Delete flow annotation must capture: mid-task cancel → 15 s wait → force remove, with a spinner / status message stage for each.
  • match_labels tag-input: adding a label (suggestion from existing repo labels when available; free-form allowed), removing a label, empty state.

Design system hygiene

  • Colour tokens, type scale, and spacing are pulled from the existing dashboard (inspect src/dashboard.html rendered in browser, lift the palette). Do not introduce a new accent colour without a note in the Penpot file explaining why.
  • Any new component (modal, tag-input, collapsible section) is specified as a Penpot component so A6's implementer can reuse its spec directly.
  • Export a minimal token list (colours + type) as a comment on this issue so the implementer can lift them into CSS without opening Penpot.

Handoff

  • Before closing this issue, post a comment with: the Penpot page URL, a per-screen screenshot (or Penpot-exported PNG), and a short note on any decision that surprised the designer during the session (e.g. "went with a drawer instead of a modal for edit because the skill viewer wanted vertical space").

Out of scope

  • Implementation (see A6 / #53).
  • Redesign of other dashboard pages — only /agents is in scope here. Other pages may reuse the components introduced by this story; that's fine.
  • Mobile layouts.
  • Dark mode — if the existing dashboard supports it, match; if not, don't introduce it.
  • Copy localisation.

References

  • Tracking issue: #47.
  • Dependent story: A6 — Dashboard agents CRUD (#53).
  • Existing dashboard: src/dashboard.html.
  • Penpot instance: design.jacquin.app (team koinos).
  • Penpot MCP wired in the interactive Claude session — use it to create / modify the file directly.

Dependencies

  • Blocked by: nothing — can run in parallel with A1–A5.
  • Blocks: A6 (implementer uses the mockup as the reference).
  • Branch off: N/A — Penpot-only, no code changes.
## User story As a **maintainer**, I want visual mockups for the `/agents` page — list view, create/edit modal, delete-confirm, skill viewer + appendix editor, and empty/error states — produced in Penpot before the implementation ticket (A6) starts, so that the CRUD UI lands with a deliberate UX rather than being designed ad-hoc at implement-time. ## Context `A6` (#53) scopes the **functional** requirements of the agents CRUD surface (endpoints, form fields, live state, cleanup-on-delete). This story covers the **design** layer upstream of it: layouts, component choices, interaction states, and copy. The operator (`@charles`) drives the Penpot session with the interactive Claude (`claude-desktop`) acting as UX designer via the Penpot MCP. The existing dashboard lives in `src/dashboard.html` and has a minimal look. The mockups should extend that vocabulary — don't introduce a new design system, use what the dashboard already uses for colours, type scale, and spacing. If gaps exist (e.g. no modal or tag-input component today), propose the minimum-viable component extension and document it in the Penpot file. ## Acceptance criteria ### Penpot file - [ ] New Penpot page in the existing `koinos` team's primary file (or a new file named `claude-hooks — dashboard`, one-off decision at the start of the session) titled `/agents`. - [ ] Design frames produced at desktop width (min 1280 px) only. Mobile is out of scope — the admin surface is desktop-only. - [ ] Page deep-link pasted as a reference in this issue before it's closed. ### Screens / states - [ ] **List view** — table of instances with columns: name, type, model (showing override with a badge when non-default), `match_labels` (chip list), queue depth, status (idle/busy/stopped pill). Sort + filter controls where they belong. Include a populated example (5–7 rows) plus an **empty state** ("No agents yet — create your first one"). - [ ] **Create modal** — form fields: type dropdown, name input (with live-validation state — valid / duplicate / invalid chars), model dropdown, `match_labels` tag-input, prompt appendix textarea (with char count), notes textarea. Show primary / secondary action affordance. - [ ] **Edit view** — same form pre-filled. Visual distinction between create and edit flows (title, button label). - [ ] **Delete-confirm modal** — show what will be cleaned up (container name, worktree count, session count), a `match_labels` preview so the operator sees what routing they're breaking, and a "Also wipe volume" checkbox with a clear destructive-action visual. Confirm button disabled until the operator types the instance name. - [ ] **Skill viewer + appendix editor** — on the edit view, a section that lists skills (`implement`, `review`, `address-review`, `rebase`, `merge`, `fix-ci`, `breakdown`). Each skill is collapsible, read-only markdown render. Next to / below it: the per-agent `prompt_appendix` textarea with live character count. Visual distinction between the immutable base and the editable appendix. - [ ] **Live-state indicators** — a component spec for the idle/busy/stopped pill and the queue-depth chip, showing each state variant. - [ ] **Error state** — a container-down instance ("stopped" status). Include the visual for the row and any banner that surfaces the underlying error (e.g. "container exited 1 — see logs"). ### Interaction specs - [ ] For each screen, annotate the happy-path flow: what clicking each action does, where focus moves, what the loading state looks like. - [ ] Delete flow annotation must capture: mid-task cancel → 15 s wait → force remove, with a spinner / status message stage for each. - [ ] `match_labels` tag-input: adding a label (suggestion from existing repo labels when available; free-form allowed), removing a label, empty state. ### Design system hygiene - [ ] Colour tokens, type scale, and spacing are pulled from the existing dashboard (inspect `src/dashboard.html` rendered in browser, lift the palette). Do not introduce a new accent colour without a note in the Penpot file explaining why. - [ ] Any new component (modal, tag-input, collapsible section) is specified as a Penpot component so A6's implementer can reuse its spec directly. - [ ] Export a minimal token list (colours + type) as a comment on this issue so the implementer can lift them into CSS without opening Penpot. ### Handoff - [ ] Before closing this issue, post a comment with: the Penpot page URL, a per-screen screenshot (or Penpot-exported PNG), and a short note on any decision that surprised the designer during the session (e.g. "went with a drawer instead of a modal for edit because the skill viewer wanted vertical space"). ## Out of scope - Implementation (see **A6** / #53). - Redesign of other dashboard pages — only `/agents` is in scope here. Other pages may reuse the components introduced by this story; that's fine. - Mobile layouts. - Dark mode — if the existing dashboard supports it, match; if not, don't introduce it. - Copy localisation. ## References - Tracking issue: #47. - Dependent story: **A6 — Dashboard agents CRUD** (#53). - Existing dashboard: `src/dashboard.html`. - Penpot instance: `design.jacquin.app` (team `koinos`). - Penpot MCP wired in the interactive Claude session — use it to create / modify the file directly. ## Dependencies - **Blocked by:** nothing — can run in parallel with A1–A5. - **Blocks:** A6 (implementer uses the mockup as the reference). - **Branch off:** N/A — Penpot-only, no code changes.
Author
Collaborator

Handoff — UX mockups for /agents

Penpot file: claude-hooks — dashboard in team peon-manager.
File: https://design.jacquin.app/#/workspace?team-id=689d7fa4-f94b-81d4-8007-e39c2a70e029&project-id=689d7fa4-f94b-81d4-8007-e39c2a7171bf&file-id=689d7fa4-f94b-81d4-8007-e39c5c82f66c

Pages

# Page Covers
01 Design tokens Dark + light palettes, type scale, spacing, radius
02 Components Buttons · Pills · Chips · Badges · Inputs · Dropdown · Textarea · Tag input · Checkbox
03 List — populated 6 rows: idle / busy (+ pulse) / stopped, model-override badge, chip labels, boss-no-labels case
04 List — empty No agents yet state + primary CTA
05 Create modal Type · Name · Model · Match labels (tag input) · Prompt appendix (with char count) · Cancel/Create
06 Edit + skill viewer Form (left) + base skills collapsible list with 1 expanded + per-instance appendix editor (right)
07 Delete confirm Cleanup preview (container, worktrees, sessions, routing, volume), destructive wipe checkbox, type-to-confirm input, 15s→force-remove progress strip
08 Error state Banner (container exited) + stopped row + interaction spec

Design tokens — lift straight into CSS

Palette is Tokyo Night Storm (dark) / Tokyo Night Day (light). One accent, two semantic-status colors, one warning for overrides:

/* ── dark (primary theme) ──────────── */
--bg:            #1A1B26;  --surface:       #24283B;  --surface-high: #2F3549;
--border:        #414868;  --text-primary:  #C0CAF5;  --text-muted:   #9AA5CE;
--text-dim:      #565F89;  --accent:        #7AA2F7;  --success:      #9ECE6A;
--warning:       #E0AF68;  --error:         #F7768E;  --info:         #7DCFFF;
--role-dev:      #BB9AF7;  --role-boss:     #7AA2F7;  --role-reviewer:#E0AF68;

/* ── light (parity theme) ──────────── */
--bg:            #E9ECF2;  --surface:       #FFFFFF;  --surface-high: #D5D6DB;
--border:        #CBD0DC;  --text-primary:  #1A1B26;  --text-muted:   #6172B0;
--text-dim:      #9AA5CE;  --accent:        #2E7DE9;  --success:      #587539;
--warning:       #8C6C3E;  --error:         #F52A65;  --info:         #007197;

/* ── type ───────────────────────────── */
font-family: 'Fira Code', 'SF Mono', 'Cascadia Code', monospace;
/* scale: 24 display · 20 h1 · 18 h2 · 16 body-lg · 13 body · 12 small · 11 meta(uppercase, ls 0.5) */
/* weights: 400 regular · 600 semibold */

/* ── spacing ────────────────────────── */
/* 4 · 8 · 12 · 16 · 24 · 32 */

/* ── radius ─────────────────────────── */
/* 4 (compact) · 6 (buttons/inputs) · 8 (cards) · 11 (pills) */

Pill / badge recipe (as rendered in the file)

.pill   { height: 22px; border-radius: 11px; padding: 0 12px; }
.pill--idle    { background: color-mix(in srgb, var(--success) 20%, transparent); color: var(--success); }
.pill--busy    { background: color-mix(in srgb, var(--accent)  20%, transparent); color: var(--accent);  /* 6px pulse dot, keyframes opacity */ }
.pill--stopped { background: color-mix(in srgb, var(--error)   20%, transparent); color: var(--error);   }
.pill--queued  { background: color-mix(in srgb, var(--warning) 20%, transparent); color: var(--warning); }
.pill-text     { font: 600 11px/1 'Fira Code', monospace; letter-spacing: 0.5px; text-transform: uppercase; }

.chip          { height: 18px; border-radius: 9px; padding: 0 10px; border: 1px solid var(--border); color: var(--text-muted); font-size: 10px; }
.chip--selected { background: color-mix(in srgb, var(--accent) 15%, transparent); border-color: var(--accent); color: var(--accent); }

.badge--override { height: 18px; border-radius: 9px; padding: 0 8px; background: color-mix(in srgb, var(--warning) 20%, transparent); color: var(--warning); font: 600 9px/1 'Fira Code', monospace; letter-spacing: 0.5px; text-transform: uppercase; }

Interaction notes (from 06 and 07)

  • List row click → navigates to /agents/:name (Edit view on page 06). Hover: row bg #2F3549 at 40% alpha.
  • New agent button → opens the create modal (page 05). Focus lands on the first field (type dropdown). ESC = cancel.
  • Delete flow (from page 07): cancel-running-task → spinner 0–15 s → force-remove container → drop SQLite row last. If partial failure, the row stays in the table in STOPPED state rather than vanishing.
  • Busy pulse dot: 2 s ease-in-out opacity 1 → 0.3, matches the existing dashboard's live-indicator keyframes (src/dashboard.html line 92).
  • match_labels tag-input: paste or comma-separated → split into chips; ✕ removes the chip immediately (no confirm); suggestions from the repo's existing label set when typing, free-form allowed.

Decisions that deviated from the issue spec

  1. Palette is new — the existing dashboard uses GitHub-inspired dark (#0d1117/#58a6ff/#3fb950). Per operator direction we switched to Tokyo Night. The AC said "don't introduce a new accent colour without a note" — this is that note. Rationale: @charles' preference, and it gives us a light-theme sibling palette for free.
  2. Light theme included — dashboard is dark-only today. Light palette shipped as a design-system deliverable so the tokens can be reused later. Recommendation: A6 ships /agents dark-only; a separate follow-up adds a theme toggle.
  3. Base components are visual specs, not Penpot Components — left as drawn shapes on page 02 rather than promoted via create_component. Rationale: implementer lifts CSS from the specs anyway, and the MCP's component-conversion makes the file harder to navigate. If the next design session wants them promoted, a five-minute pass in the Penpot UI will do it.
  4. Edit view = side-by-side — spec said "next to it / below it" for the appendix editor. We went side-by-side (form on left, skills + appendix on right). The appendix sits inside the skills card at the bottom, visually distinct via a warning-colored stroke (--warning) to signal "editable, per-instance" against the muted/read-only skills above.
  5. auth-token pre-seeded cookie path in the MCP — our Penpot instance has login-with-password disabled (OIDC-only) and access tokens off, so the Penpot MCP needed a patched auth path (cookie injection + Authelia Basic proxy-auth). Not design-relevant, but worth flagging if a future session tries to reuse the MCP.

What's not covered here (stays out of scope per AC)

  • Mobile layouts.
  • Dark-mode toggle UI (palette exists, toggle does not).
  • Copy localisation.
  • Redesign of /tasks or /storage.

Ready for A6 (#53) to pick up.

## Handoff — UX mockups for `/agents` Penpot file: **claude-hooks — dashboard** in team `peon-manager`. File: https://design.jacquin.app/#/workspace?team-id=689d7fa4-f94b-81d4-8007-e39c2a70e029&project-id=689d7fa4-f94b-81d4-8007-e39c2a7171bf&file-id=689d7fa4-f94b-81d4-8007-e39c5c82f66c ### Pages | # | Page | Covers | |---|------|--------| | 01 | `Design tokens` | Dark + light palettes, type scale, spacing, radius | | 02 | `Components` | Buttons · Pills · Chips · Badges · Inputs · Dropdown · Textarea · Tag input · Checkbox | | 03 | `List — populated` | 6 rows: idle / busy (+ pulse) / stopped, model-override badge, chip labels, boss-no-labels case | | 04 | `List — empty` | `No agents yet` state + primary CTA | | 05 | `Create modal` | Type · Name · Model · Match labels (tag input) · Prompt appendix (with char count) · Cancel/Create | | 06 | `Edit + skill viewer` | Form (left) + base skills collapsible list with 1 expanded + per-instance appendix editor (right) | | 07 | `Delete confirm` | Cleanup preview (container, worktrees, sessions, routing, volume), destructive wipe checkbox, type-to-confirm input, 15s→force-remove progress strip | | 08 | `Error state` | Banner (container exited) + stopped row + interaction spec | ### Design tokens — lift straight into CSS Palette is **Tokyo Night Storm** (dark) / **Tokyo Night Day** (light). One accent, two semantic-status colors, one warning for overrides: ```css /* ── dark (primary theme) ──────────── */ --bg: #1A1B26; --surface: #24283B; --surface-high: #2F3549; --border: #414868; --text-primary: #C0CAF5; --text-muted: #9AA5CE; --text-dim: #565F89; --accent: #7AA2F7; --success: #9ECE6A; --warning: #E0AF68; --error: #F7768E; --info: #7DCFFF; --role-dev: #BB9AF7; --role-boss: #7AA2F7; --role-reviewer:#E0AF68; /* ── light (parity theme) ──────────── */ --bg: #E9ECF2; --surface: #FFFFFF; --surface-high: #D5D6DB; --border: #CBD0DC; --text-primary: #1A1B26; --text-muted: #6172B0; --text-dim: #9AA5CE; --accent: #2E7DE9; --success: #587539; --warning: #8C6C3E; --error: #F52A65; --info: #007197; /* ── type ───────────────────────────── */ font-family: 'Fira Code', 'SF Mono', 'Cascadia Code', monospace; /* scale: 24 display · 20 h1 · 18 h2 · 16 body-lg · 13 body · 12 small · 11 meta(uppercase, ls 0.5) */ /* weights: 400 regular · 600 semibold */ /* ── spacing ────────────────────────── */ /* 4 · 8 · 12 · 16 · 24 · 32 */ /* ── radius ─────────────────────────── */ /* 4 (compact) · 6 (buttons/inputs) · 8 (cards) · 11 (pills) */ ``` ### Pill / badge recipe (as rendered in the file) ```css .pill { height: 22px; border-radius: 11px; padding: 0 12px; } .pill--idle { background: color-mix(in srgb, var(--success) 20%, transparent); color: var(--success); } .pill--busy { background: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent); /* 6px pulse dot, keyframes opacity */ } .pill--stopped { background: color-mix(in srgb, var(--error) 20%, transparent); color: var(--error); } .pill--queued { background: color-mix(in srgb, var(--warning) 20%, transparent); color: var(--warning); } .pill-text { font: 600 11px/1 'Fira Code', monospace; letter-spacing: 0.5px; text-transform: uppercase; } .chip { height: 18px; border-radius: 9px; padding: 0 10px; border: 1px solid var(--border); color: var(--text-muted); font-size: 10px; } .chip--selected { background: color-mix(in srgb, var(--accent) 15%, transparent); border-color: var(--accent); color: var(--accent); } .badge--override { height: 18px; border-radius: 9px; padding: 0 8px; background: color-mix(in srgb, var(--warning) 20%, transparent); color: var(--warning); font: 600 9px/1 'Fira Code', monospace; letter-spacing: 0.5px; text-transform: uppercase; } ``` ### Interaction notes (from `06` and `07`) - **List row click** → navigates to `/agents/:name` (Edit view on page 06). Hover: row bg `#2F3549` at 40% alpha. - **New agent button** → opens the create modal (page 05). Focus lands on the first field (type dropdown). ESC = cancel. - **Delete flow** (from page 07): cancel-running-task → spinner 0–15 s → force-remove container → drop SQLite row last. If partial failure, the row stays in the table in `STOPPED` state rather than vanishing. - **Busy pulse dot**: 2 s ease-in-out opacity 1 → 0.3, matches the existing dashboard's live-indicator keyframes (`src/dashboard.html` line 92). - **`match_labels` tag-input**: paste or comma-separated → split into chips; ✕ removes the chip immediately (no confirm); suggestions from the repo's existing label set when typing, free-form allowed. ### Decisions that deviated from the issue spec 1. **Palette is new** — the existing dashboard uses GitHub-inspired dark (`#0d1117`/`#58a6ff`/`#3fb950`). Per operator direction we switched to Tokyo Night. The AC said "don't introduce a new accent colour without a note" — this *is* that note. Rationale: @charles' preference, and it gives us a light-theme sibling palette for free. 2. **Light theme included** — dashboard is dark-only today. Light palette shipped as a *design-system deliverable* so the tokens can be reused later. Recommendation: A6 ships `/agents` dark-only; a separate follow-up adds a theme toggle. 3. **Base components are visual specs, not Penpot Components** — left as drawn shapes on page 02 rather than promoted via `create_component`. Rationale: implementer lifts CSS from the specs anyway, and the MCP's component-conversion makes the file harder to navigate. If the next design session wants them promoted, a five-minute pass in the Penpot UI will do it. 4. **Edit view = side-by-side** — spec said "next to it / below it" for the appendix editor. We went side-by-side (form on left, skills + appendix on right). The appendix sits *inside* the skills card at the bottom, visually distinct via a warning-colored stroke (`--warning`) to signal "editable, per-instance" against the muted/read-only skills above. 5. **`auth-token` pre-seeded cookie path in the MCP** — our Penpot instance has `login-with-password` disabled (OIDC-only) and access tokens off, so the Penpot MCP needed a patched auth path (cookie injection + Authelia Basic proxy-auth). Not design-relevant, but worth flagging if a future session tries to reuse the MCP. ### What's *not* covered here (stays out of scope per AC) - Mobile layouts. - Dark-mode toggle UI (palette exists, toggle does not). - Copy localisation. - Redesign of `/tasks` or `/storage`. Ready for A6 (#53) to pick up.
Author
Collaborator

Closing as retroactively-obsolete. A6 (#53 / #116) shipped the agents CRUD ad-hoc during milestone 16 without this Penpot mockup upstream — the design decisions were made at implementation time and documented in the resulting code. Reintroducing the mockup now would be post-hoc documentation of what already ships.

If you want a Penpot record of the current dashboard surface (both for team handoff and to unblock future design iteration), that's a fresh area:design ticket scoped to "mockup the dashboard as it currently ships" — cleaner than trying to retcon this one.

Closes with milestone 16.

Closing as retroactively-obsolete. A6 (#53 / #116) shipped the agents CRUD ad-hoc during milestone 16 without this Penpot mockup upstream — the design decisions were made at implementation time and documented in the resulting code. Reintroducing the mockup now would be post-hoc documentation of what already ships. If you want a Penpot record of the current dashboard surface (both for team handoff and to unblock future design iteration), that's a fresh `area:design` ticket scoped to "mockup the dashboard as it currently ships" — cleaner than trying to retcon this one. Closes with milestone 16.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#55
No description provided.