first commit
This commit is contained in:
271
design_handoff_helder_workbench/README.md
Normal file
271
design_handoff_helder_workbench/README.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# Handoff: Helder — AI Code Workbench (Electron)
|
||||
|
||||
## Overview
|
||||
**Helder** is a desktop code workbench for a developer who reviews and works with code written by an AI agent. It is a dense, four-column IDE-style window optimized for an ultrawide monitor (designed at **3440×1440**, but fully fluid down to ~1280px wide). It is **dark mode only** — there is intentionally no light theme and no theme toggle.
|
||||
|
||||
The core jobs the app supports:
|
||||
- Fast project navigation + a single search that covers **both file contents and file names**.
|
||||
- A Git review surface (commit box, staged list, changes list, per-file diff with four view modes).
|
||||
- An editor with tabs and syntax-colored code.
|
||||
- A live **Claude Code agent** terminal plus a normal shell terminal.
|
||||
- A right-click **"Copy reference"** / **"Pass on to Agent"** flow that pushes `path:line` references into the agent's input so the developer can quickly point the agent at code.
|
||||
|
||||
## About the Design Files
|
||||
The files in `design/` are a **design reference created in HTML/CSS/React-via-Babel** — a working prototype that shows the intended look, layout, and behavior. **They are not the production codebase and should not be shipped as-is.**
|
||||
|
||||
The task is to **recreate this design as a real Electron application**, using a proper build setup and the patterns below. The prototype loads React 18 + Babel from a CDN and stores everything in mock data; the real app should use a normal toolchain (see "Recommended Electron Stack"). Treat the HTML as the source of truth for *visual + interaction design*, and this README as the source of truth for *structure, tokens, and behavior*.
|
||||
|
||||
You can open `design/Helder - AI Code Workbench.html` directly in a browser to see and click the live prototype while building.
|
||||
|
||||
## Fidelity
|
||||
**High-fidelity (hifi).** Colors, typography, spacing, diff coloring, and interactions are final. Recreate the UI pixel-faithfully. All exact values are in the Design Tokens section and in `design/styles.css` (the prototype's `:root` block is the canonical token list).
|
||||
|
||||
---
|
||||
|
||||
## Recommended Electron Stack
|
||||
No target codebase exists yet, so choose a modern, conventional setup:
|
||||
- **Electron** (latest stable) with a **main** process and a **renderer**.
|
||||
- **Renderer:** React 18 + TypeScript + Vite (`electron-vite` is a good scaffold). The prototype is already React, so component structure ports directly.
|
||||
- **Syntax highlighting:** the prototype uses **Prism 1.29** (`prism-core` + `markup-templating`, `php`, `python`, `typescript`, `json`, `bash`, `markdown`). Keep Prism, or swap to **Shiki**/**CodeMirror 6** if you prefer; the token→color mapping is documented below. **Important Prism gotcha:** `prism-php` requires `prism-markup-templating` to be loaded **first**, or every `Prism.highlight` call throws and silently falls back to plain text.
|
||||
- **Fonts:** UI = system stack (`-apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif`); code/mono = **JetBrains Mono** (bundle the font locally for offline use — do not rely on Google Fonts CDN in Electron).
|
||||
- **Real integrations to wire up (replacing the mock):**
|
||||
- File tree + file contents → real FS via the main process (`fs`, `chokidar` for watching). Never touch FS directly from the renderer; use IPC / a preload bridge with `contextIsolation: true`.
|
||||
- Git panel → shell out to `git` (or `simple-git`) for `status --porcelain`, staged/unstaged sets, `add`/`reset`, `commit`, and `diff`. The prototype computes diffs in JS with an LCS; in the real app prefer `git diff` output, but the four view modes still derive from an original/updated text pair per file.
|
||||
- Terminals → real PTYs via **node-pty** + **xterm.js**. The "Claude agent" pane is just a terminal that runs the `claude` CLI; the bottom pane is a normal shell. The prototype fakes both — see "Terminals".
|
||||
- Search → ripgrep (`rg`) for content search; a fast fuzzy matcher (e.g. `fzf`-style or `fuse.js`) for file-name search.
|
||||
- "Copy reference" → Electron `clipboard.writeText`.
|
||||
- "Pass on to Agent" → write into the agent terminal's PTY using **bracketed paste** (`\x1b[200~` … `\x1b[201~`) so the `claude` CLI treats it as pasted input and does NOT submit it. This is the real mechanism the prototype only simulates.
|
||||
|
||||
---
|
||||
|
||||
## Global Layout
|
||||
|
||||
Top-level vertical stack (`.app`, `height:100vh`, `display:flex; flex-direction:column`):
|
||||
|
||||
1. **Title bar** — `height: 36px`, fixed.
|
||||
2. **Workbench** — `flex: 1`, a horizontal flex row of four columns separated by draggable splitters.
|
||||
3. **Status bar** — `height: 23px`, fixed.
|
||||
|
||||
**Design principle the client asked for:** keep the chrome minimal — title bar + tab strip + panel headers + status bar combined should stay ≈10% of vertical height so code and tools own the screen.
|
||||
|
||||
### Workbench columns (left → right)
|
||||
All columns are **horizontally resizable** by dragging the 5px splitter between them. The editor is the flex-grow column; the other three have explicit pixel widths with min/max clamps.
|
||||
|
||||
| # | Column | Default width | Min–Max | Notes |
|
||||
|---|--------|---------------|---------|-------|
|
||||
| 1 | **Source Control** (Git) | 232px | 160–460 | commit box + staged list + changes list |
|
||||
| 2 | **Explorer** (file tree) | 244px | 160–520 | VS Code-style tree, colored type icons |
|
||||
| 3 | **Editor** | flex:1 | min 240px | tabs + code/diff |
|
||||
| 4 | **Right column** | 444px | 280–780 | split vertically: agent terminal (top) + shell (bottom), draggable horizontal splitter, default top fraction 0.52 |
|
||||
|
||||
Splitter: 5px hit area, transparent; inner 1px line is `--border`, turning to `--accent` (0.55 alpha) on hover/drag. Vertical splitter cursor `col-resize`; horizontal `row-resize`.
|
||||
|
||||
---
|
||||
|
||||
## Screens / Components
|
||||
|
||||
### 1. Title bar (`.titlebar`)
|
||||
- Height 36px, background `--bg-3`, bottom border `--border`, horizontal padding 12px, items gap 14px.
|
||||
- Left → right:
|
||||
- **Traffic lights**: three 12px circles, gap 8px — red `#e0696a`, yellow `#d8a85c`, green `#5cbd6b`. (On macOS use the native frame instead; these are decorative in the web prototype.)
|
||||
- **Wordmark**: a small spark/diamond icon in `--accent`, then **`Helder`** (weight 600, `--fg-0`), an em-dash in `--fg-3`, then the project name (`console`) in `--fg-2`. Font 12px.
|
||||
- **Breadcrumb** of the active file path, monospace 11.5px, `--fg-3`, segments joined by ` › `; last segment `--fg-1`.
|
||||
- Spacer (flex:1).
|
||||
- **Search button**: `.tb-btn` — ghost button, 11.5px, `--fg-2`; search icon + "Search" + a `<kbd>⌘F</kbd>` chip. Hover → `--hover` bg, `--fg-0` text. (There is intentionally **no "Go to File" button** — search covers file names too.)
|
||||
|
||||
### 2. Source Control panel (`.col` #1)
|
||||
Order, top to bottom:
|
||||
|
||||
**a. Panel header** (`.phead`, height 30px): branch icon + "SOURCE CONTROL" (uppercase, 10.5px, letter-spacing .09em, `--fg-2`) + a count pill on the right showing the number of changed (uncommitted) files.
|
||||
|
||||
**b. Commit box** (`.commit-box`, padding 9px 10px, bottom border): a flex row, `align-items:flex-start`, gap 7px.
|
||||
- **Message field**: a 1-row auto-growing `<textarea>` (`.commit-input`), flex:1, bg `--bg-0`, 1px `--border-2` border, radius 7px, padding 7px 9px, font UI 12px, min-height 32px; focus border `--accent-line`. Placeholder: `Message (⌘↵ to commit)`.
|
||||
- **Commit button** (`.commit-btn`): solid `--accent` bg, text `#0c1320`, weight 600, radius 7px, height 32px, padding 0 11px; a check icon + label `Commit` (or `Commit N` when N files are staged). **Disabled** (bg `--bg-3`, text `--fg-3`, `not-allowed`) unless there is ≥1 staged file AND a non-empty message. `⌘↵`/`Ctrl+↵` in the field commits.
|
||||
|
||||
**c. Two stacked lists** (`.git-body`, scrolls). Both lists are **always present** even when empty:
|
||||
- **Staged Changes** group header (`.git-group`) with count; on hover shows an "unstage all" `−` button on the right. Below it, the staged file rows — or, if empty, the hint `Nothing staged — use + to stage a file` (`.git-none`).
|
||||
- A 1px **divider** (`.git-divider`, `--border`, margin 8px 12px 2px).
|
||||
- **Changes** group header with count; hover shows a "stage all" `+` button. Below it, the unstaged rows — or hint `All changes staged`.
|
||||
- If the working tree is fully clean (everything committed), show a centered empty state: a green check icon + `No changes — working tree clean`.
|
||||
|
||||
**Git file row** (`.git-row`, padding 3px 12px 3px 14px, gap 8px, `cursor:pointer`):
|
||||
- **Status letter** (`.git-stat`, mono 11px bold, 13px wide): `M` = `--mod` (amber), `A` = `--add` (green), `D` = `--del` (red), `R` = `--ren` (blue).
|
||||
- **File-type icon** (see Explorer).
|
||||
- **File name** (`--fg-1`; deleted files get `line-through` + `--fg-3`).
|
||||
- **Directory** (`.git-dir`): the parent path, `--fg-3`, 11px, right-aligned with `direction:rtl` ellipsis, max-width ~42%.
|
||||
- **Stage/unstage button** (`.git-act`): appears on row hover, 20×20, a `+` (stage) on Changes rows or `−` (unstage) on Staged rows.
|
||||
- **Delta** (`.git-delta`, mono 10.5px): `+N` in `--add`, `-N` in `--del`.
|
||||
- Hover bg `--hover`; active (open in editor) bg `--sel` + 2px `--accent` left rail.
|
||||
- **Click** opens the file's diff in the editor. **Right-click** → context menu (see Interactions).
|
||||
|
||||
**d. Footer** (`.git-foot`): branch icon + branch name (`--fg-0` bold) on the left; total `+adds`/`-dels` (mono) on the right.
|
||||
|
||||
> Seed/demo data: branch `feat/payments-balance`; 6 changed files; 2 pre-staged (`PaymentService.php` [A], `config/app.json` [M]); 4 unstaged including a deleted `LegacyUser.php` [D].
|
||||
|
||||
### 3. Explorer / file tree (`.col` #2)
|
||||
- Header `.phead`: "EXPLORER" + project name (`console`) right-aligned, mono 10.5px `--fg-3`.
|
||||
- Tree body scrolls. Rows are 23px tall.
|
||||
- **Folder row** (`.tree-row.folder`): a rotating chevron (▸ closed → ▾ open, CSS rotate 90°, .12s) + a simple folder glyph + name (`--fg-1`). Click toggles expand. Indent = `10 + depth*13` px.
|
||||
- **File row**: file-type icon + name. Active file → `--sel` bg + 2px `--accent` left rail. Files with an uncommitted change show a status letter badge (`M`/`A`/`D`) on the right (cleared once that file is committed). Deleted files render struck-through.
|
||||
- **File-type icon** (`.ficon`): a **15×15 rounded-square monogram chip** filled with a per-type color, containing 1–3 dark glyph characters (`#0c0d0f`, mono 7.5px bold). Do **not** use brand logos. Colors/labels:
|
||||
- `.php` → `#a78bdb` "php" · `.js/.mjs` → `#e6c860` "js" · `.ts/.tsx` → `#5a9bd6` "ts" · `.py` → `#5fa8d6` "py" · `.html` → `#e08b6a` "<>" · `.css` → `#5a9bd6` "{}" · `.json` → `#d8a85c` "{}" · `.md` → `#9aa0a8` "md" · `.env/.sh` → `#7fc6a0` "$" · `.yml/.yaml` → `#cf7a6a` "yml".
|
||||
- Special names: `composer.json` `#a78bdb` "co"; `package.json` `#cf7a6a` "pk"; `README.md` `#5a9bd6` "md"; `.env` `#7fc6a0` "$".
|
||||
- Default/unknown: `#7d838c`, first two letters of the name.
|
||||
|
||||
### 4. Editor (`.col` #3)
|
||||
**Tab strip** (`.tabs`, height 35px, bg `--bg-3`, horizontal scroll, no scrollbar):
|
||||
- **Tab** (`.tab`): file-type icon + name, 12.5px, max-width 230px. Inactive `--bg-3`/`--fg-2`; active `--bg-0`/`--fg-0` with a 2px `--accent` top rail. A small mode badge (`.tab-mode`: `orig`/`upd`/`diff`/`split`) shows for changed files. A close `×` (`.tclose`, 17px) on the right; **middle-click** also closes. Hover bg `#272b31`.
|
||||
|
||||
**Diff toolbar** (`.diff-bar`, only shown for changed files; height 26px, bg `--bg-3`):
|
||||
- Left: a status word (`Modified`/`Added`/`Deleted`) tinted by status, then `+N` (green) / `−N` (red).
|
||||
- Right: a **4-segment control** (`.seg`, 1px `--border-2`, radius 7px): **Original · Updated · Diff · [⊟ Split]**. Active segment bg `--accent-soft`, text `--fg-0`. The Split segment carries a small split-pane icon.
|
||||
|
||||
**Code area** (`.editor`, mono 13px, line-height 20px, scrolls). Each line is a flex row (`.ln-row`):
|
||||
- **Gutter** (`.ln-gutter`, 54px, right-aligned, `--fg-3`, clickable to select that line; shift-click extends a range).
|
||||
- (Diff mode only) a **sign column** (`.ln-sign`, 14px): `+`/`-`.
|
||||
- **Code** (`.ln-code`, `white-space:pre`), syntax-highlighted.
|
||||
- Cursor line gets a faint `rgba(255,255,255,.035)` bg; selected range gets `--accent-soft`.
|
||||
|
||||
**The four view modes** (all are presentations of the same per-file diff; same color language everywhere → **red = removed / changed-from, green = added / changed-to**; syntax highlighting stays on in all four):
|
||||
1. **Original** — the pre-edit file, read-only. Removed/changed lines get a **red gutter bar** (`box-shadow: inset 2px 0 0 var(--del)` on the row). No inline +/- markers.
|
||||
2. **Updated** — the current/live file. Added/changed lines get a **green gutter bar** (`inset 2px 0 0 var(--add)`). (In the real app this is the editable buffer.)
|
||||
3. **Diff** — single-pane unified inline diff: removed lines red with `-`, added lines green with `+`, full file context in sequence. This is the default when a changed file is opened.
|
||||
4. **Split** — clicking it opens a **full-screen overlay** (`.split-overlay`, `position:fixed; inset:0; z-index:60`) covering all panels: header bar (file icon + path + status + `+/−`) with a **Collapse** button + `Esc` to exit; body is two side-by-side panes — **Original** left, **Updated** right — with lines aligned (blank padded rows where one side has no counterpart, rendered with a faint diagonal hatch `.ln-row.empty`), red bars on the left, green bars on the right, and **synced vertical scrolling** between panes.
|
||||
|
||||
Empty editor state (`.empty-ed`): file icon + "No file open" + a key-hint list (`Search files & content ⌘F`, `Copy reference right-click`, `Pass on to Agent right-click`).
|
||||
|
||||
### 5. Right column — terminals (`.col` #4)
|
||||
Two stacked terminal panes split by a draggable horizontal splitter (top fraction default 0.52).
|
||||
|
||||
Each pane:
|
||||
- **Header** (`.term-head`, height 28px, bg `--bg-3`): a status dot (the agent pane's dot is green + pulsing when a session is live), a mono label (`claude` / `zsh`), and a right-aligned tag (`agent session` / `— bash · ~/console`).
|
||||
- **Body** (`.term-body`, mono 12.5px, line-height 18px, scrolls, `cursor:text`): a stream of output lines plus an input row at the bottom.
|
||||
- **Input row** (`.term-input`): a colored prompt glyph (agent `>` in violet `#c98bdb`; shell `console %` with `%` in `--fg-3`) + a transparent auto-growing **`<textarea>`** (`.term-ta`, mono 12.5px, `caret-color:--accent`, up to 8 rows). **Enter** submits; **Shift+Enter** inserts a newline; ↑/↓ recall history (only when the buffer has no newline).
|
||||
|
||||
**Agent pane behavior (top):** it is a terminal. Typing `claude` "boots" an agent session (a bordered welcome card + intro line). In a live session, submitting a prompt streams a short simulated response: a "thinking…" line, `read`/`grep` tool lines, an **edit card** (`.term-card` — a bordered block with a header `edit · <path>` and red `-`/green `+` rows), then a green "Done" line. `/exit` ends the session. **In the real app, replace all of this with a real PTY running the `claude` CLI** (node-pty + xterm.js). The simulated content (`agentSeed`, `runAgent`, `bootAgent` in `design/src/terminals.jsx`) is only there to show the intended visual style — keep that styling, drop the fakery.
|
||||
|
||||
**Shell pane (bottom):** a normal terminal. The prototype fakes `ls`, `pwd`, `cat`, `git status`, `git diff`, `echo`, `clear`; replace with a real shell PTY.
|
||||
|
||||
### 6. Status bar (`.statusbar`, height 23px, bg `--bg-3`, 11px)
|
||||
Segments left→right: an **accent-colored** branch chip (bg `--accent`, text `#0c1320`); `+adds / −dels`; spacer; cursor position (`Ln X, Col Y`, or `N lines selected`); `Spaces: 4`; `UTF-8`; active file language (bold); and the current view mode word (`Original`/`Updated`/`Diff`/`Split`) when a changed file is active. Each segment hover bg `--hover`.
|
||||
|
||||
---
|
||||
|
||||
## Interactions & Behavior
|
||||
|
||||
### Search (⌘F) — `SearchModal`
|
||||
- Opened by `⌘F` / `Ctrl+F` or the title-bar Search button. (There is no separate "go to file" command; this one modal does both.)
|
||||
- A scrim (`.scrim`, `rgba(8,9,11,.5)`, slight blur) with a **large centered modal** (`.search-modal`, width 940px, max 94vw).
|
||||
- Top: a single text input (search icon + field, placeholder `Search content and file names…`) and a right-aligned count chip (`N hits · M files`).
|
||||
- Body is **two columns**:
|
||||
- **Left — Content** (`.sc-left`, flex-grow, the wide pane, max-height 460px, scrolls): substring matches across all file contents (case-insensitive, min 2 chars), grouped by file. Each group: a file header (icon + path + hit count); then up to 12 matching lines, each `line# + the line text with the matched term wrapped in <mark>` (`mark` bg `rgba(216,168,92,.28)`). Clicking a line opens that file at that line.
|
||||
- **Right — Files** (`.sc-right`, **fixed 256px — deliberately narrower**, max-height 460px, scrolls, slightly darker bg): fuzzy matches on file name (then path), each a 2-line cell (name with matched chars bolded in `--accent` + dimmed dir path). A `•` dot marks files with uncommitted changes. Clicking opens the file.
|
||||
- Section headers (`.sc-head`) are sticky, uppercase 10px, with a count pill.
|
||||
- **Keyboard:** ↑/↓ move a selection through the flat list of content hits (selected line highlighted `--accent-soft`); **Enter** opens the selected content hit (or the first file if there are no content hits); **Esc** closes. Clicking the scrim closes.
|
||||
|
||||
### Right-click in the editor → context menu (`.ctx`) — exactly two items
|
||||
1. **Copy reference** — copies a **project-relative** reference to the clipboard:
|
||||
- No selection: `path:line` (e.g. `src/Http/Controller/UserController.php:42`).
|
||||
- With a selection: `path:start-end` (e.g. `src/Http/Controller/UserController.php:42-58`).
|
||||
- The clicked line is resolved via `document.caretRangeFromPoint`; a multi-line text selection (or a gutter range-select) yields the start-end form.
|
||||
2. **Pass on to Agent** — opens a small **inline popup** (`.pass-pop`) anchored at the click:
|
||||
- A header (`✦ Pass on to Agent` + `esc` chip), one optional single-line text field (placeholder `Add a note (optional)…`), an `INSERTS` preview showing the composed line, and a footer `↵ insert into agent · esc cancel`.
|
||||
- On **Enter**: compose ONE line = `<typed note> <reference>` (just the bare reference if the field is empty) and insert it into the **agent terminal's input** as a **new, unsubmitted line, leaving the caret on a fresh line below** — so the action can be repeated to **stack several references** before the developer presses Enter to send. **Insert never submits.** In the real app, do this by writing the text to the agent PTY wrapped in **bracketed paste** (`\x1b[200~ … \x1b[201~`).
|
||||
- **Esc** cancels with no insert; clicking outside cancels.
|
||||
- The context menu shows the resolved reference as a muted note at the top.
|
||||
- The menu reuses a generic popup also used by tree/git rows; **only the editor menu is the two-item Copy/Pass menu.** Tree rows offer Copy reference / Send reference to agent / Copy file name / Open / Reveal; Git rows additionally offer **Stage changes** or **Unstage changes** and **Open diff**.
|
||||
|
||||
### Diff mode switching
|
||||
- Clicking Original/Updated/Diff sets the active tab's mode and closes any open Split overlay. Clicking Split opens the full-screen overlay; the previous mode is preserved for when you collapse. `Esc` collapses Split.
|
||||
- Opening a file from the Git panel defaults to **Diff**; opening from search/tree defaults to the plain file (**Updated** for changed files so line numbers map to the current content).
|
||||
|
||||
### Staging / commit
|
||||
- Hover a git row → `+`/`−` to stage/unstage; group headers have stage-all/unstage-all. Right-click → Stage/Unstage.
|
||||
- Commit (button or `⌘↵`) moves staged files out of the working set, clears the message, shows a toast `Committed N file(s)`, and clears those files' badges in the tree.
|
||||
|
||||
### Toasts (`.toast-wrap`, bottom-center)
|
||||
- Small dark pill with an icon, a title, and (optionally) a mono reference chip in `--accent`. Auto-dismiss after ~2.3s. Used for "Copied reference", "Passed to agent", "Committed N files".
|
||||
|
||||
### Keyboard shortcuts
|
||||
- `⌘F` / `Ctrl+F` — open Search.
|
||||
- `⌘W` / `Ctrl+W` — close active tab.
|
||||
- `Esc` — collapse Split if open, else close any overlay/menu.
|
||||
- `⌘↵` in commit box — commit.
|
||||
- In terminals: `Enter` submit, `Shift+Enter` newline, `↑/↓` history.
|
||||
|
||||
### Animations
|
||||
- Chevron rotate .12s. Splitter line color .12s. Overlays/toasts a ~.12s ease-out entrance (translateY 6–8px). Live agent dot: a 2.2s pulsing box-shadow ring. Keep motion subtle; respect `prefers-reduced-motion`.
|
||||
|
||||
---
|
||||
|
||||
## State Management
|
||||
Renderer state (the prototype keeps all of this in the top `App` component; in the real app, lift FS/git/terminal state into the main process and stream via IPC):
|
||||
- `openTabs: string[]` (file paths), `activeTab`, `tabMode: Record<path, 'original'|'updated'|'diff'|'code'>`.
|
||||
- `splitFor: path | null` (which file is in full-screen Split).
|
||||
- `openDirs: Set<path>` (expanded tree folders).
|
||||
- `cursor: {path, line, col}`, `selection: {path, start, end} | null`.
|
||||
- `overlay: 'search' | null`, `menu` (context menu descriptor), `passPopup: {x,y,ref} | null`, `toasts[]`.
|
||||
- Git: `staged: Set<path>`, `committed: Set<path>`, `commitMsg`.
|
||||
- Column sizes: `gitW`, `treeW`, `rightW` (px) + the right column's top-pane fraction.
|
||||
- Per changed file the app needs an **original text** and **updated text**; the diff (`rows` for unified, `left`/`right` for Original/Updated with per-line add/del marks, and `split` aligned pairs, plus `+`/`−` counts) is derived from those. See `buildDiff()` in `design/src/data.js` for the exact derivation (LCS line diff) — in production prefer real `git diff` but keep the same four derived views.
|
||||
|
||||
## Data the real app must supply (replacing `design/src/data.js`)
|
||||
- Project file tree (nested dirs/files) from the opened folder.
|
||||
- File contents on demand.
|
||||
- Git: current branch, changed files with status (`A/M/D/R`) and `+/−` counts, staged/unstaged sets, and original+updated text per changed file.
|
||||
- Search: content matches (ripgrep) and file-name matches (fuzzy).
|
||||
|
||||
---
|
||||
|
||||
## Design Tokens
|
||||
Canonical source: the `:root` block in `design/styles.css`. Key values:
|
||||
|
||||
**Surfaces / neutrals (cool charcoal):**
|
||||
- `--bg-0 #16171a` (editor) · `--bg-1 #1a1c1f` (terminals) · `--bg-2 #1f2226` (sidebars) · `--bg-3 #23262b` (headers/tabs)
|
||||
- `--hover #2a2e34` · `--active #313742` · `--sel #2b323d`
|
||||
- `--border #2a2d33` · `--border-2 #34383f`
|
||||
- Text: `--fg-0 #e6e8ea` · `--fg-1 #b4bac2` · `--fg-2 #838a94` · `--fg-3 #5d636c`
|
||||
|
||||
**Accent (single, cool blue):**
|
||||
- `--accent #4d8dff` · `--accent-soft rgba(77,141,255,.16)` · `--accent-line rgba(77,141,255,.55)`
|
||||
|
||||
**Git / diff status:**
|
||||
- `--add #5cbd6b` · `--del #e0696a` · `--mod #d8a85c` · `--ren #5aa6d6`
|
||||
- `--add-bg rgba(92,189,107,.10)` · `--del-bg rgba(224,105,106,.10)`
|
||||
|
||||
**Syntax tokens (tuned to charcoal):**
|
||||
- keyword `--t-key #c98bdb` · string `--t-str #94c980` · number `--t-num #e0a06a` · function `--t-fn #6aa6f0` · comment `--t-com #5f656e` (italic) · tag `--t-tag #7fc6a0` · attr-name `--t-attr #d8b15c` · punctuation `--t-punc #9aa0a8` · variable `--t-var #e6e8ea` · constant/boolean/builtin `--t-const #e08b6a` · property `--t-prop #6ec0c0`
|
||||
- (See the `.ln-code .token.*` rules in `design/styles.css` for the full Prism token→variable mapping.)
|
||||
|
||||
**Typography:**
|
||||
- UI: `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif`. Base 13px.
|
||||
- Mono: `"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace`. Editor 13px / line-height 20px; terminals 12.5px / 18px.
|
||||
- Panel headers: 10–10.5px uppercase, letter-spacing ~.08em.
|
||||
|
||||
**Radii / spacing:** card/control radii 6–11px (panels 7px, modals 10–11px, chips 4–5px). Icon chips 15px / radius 3.5px. Splitters 5px. Column gaps are the splitters; inside panels use the paddings noted per component.
|
||||
|
||||
**Shadows:** menus/popovers `0 16px 44px rgba(0,0,0,.5)`; modals `0 24px 70px rgba(0,0,0,.55)`; toasts `0 12px 34px rgba(0,0,0,.45)`.
|
||||
|
||||
## Assets
|
||||
- **No raster/brand assets.** All icons are simple inline SVGs (geometric: search, branch, close, copy, terminal, spark/diamond, file, folder, diff, plus, minus, check, discard, expand/collapse) — see the `Icon` map in `design/src/components.jsx`. File-type icons are colored monogram chips (no third-party logos). Recreate these as a small icon set (or substitute an open icon library like Lucide for the UI icons, keeping the monogram chips for file types).
|
||||
- **Font:** JetBrains Mono (OFL) — bundle locally.
|
||||
|
||||
## Files in this bundle
|
||||
- `design/Helder - AI Code Workbench.html` — entry point; open in a browser to view the live prototype.
|
||||
- `design/styles.css` — all styling + the canonical design-token `:root` block.
|
||||
- `design/src/data.js` — mock filesystem, git changes, before/after file pairs, and the `buildDiff()` LCS diff that powers the four view modes. **Replace with real FS/git data.**
|
||||
- `design/src/highlight.js` — Prism language/ext mapping + monogram file-icon metadata.
|
||||
- `design/src/components.jsx` — `Icon` set, `FileIcon`, `GitPanel`/`GitRow`, `FileTree`.
|
||||
- `design/src/editor.jsx` — tabs, the four-mode editor (`PaneView`, `buildLines`), and the full-screen `SplitView`.
|
||||
- `design/src/terminals.jsx` — the agent + shell terminal component and the simulated session (replace the simulation with real PTYs).
|
||||
- `design/src/overlays.jsx` — `SearchModal`, `ContextMenu`, `PassPopup`, `Toasts`.
|
||||
- `design/src/app.jsx` — composition: layout, resizable splitters, keyboard shortcuts, git/commit/stage logic, copy-reference + pass-to-agent wiring.
|
||||
|
||||
## Implementation order (suggested)
|
||||
1. Electron shell + frameless dark window; port tokens to CSS variables; bundle JetBrains Mono.
|
||||
2. Static layout: four resizable columns + title/status bars.
|
||||
3. Real file tree + open files into tabs (read-only) with Prism highlighting.
|
||||
4. Git panel from `git status` (read-only), then staging + commit, then the four diff modes + Split.
|
||||
5. Search (ripgrep + fuzzy).
|
||||
6. Terminals via node-pty + xterm.js; run `claude` in the agent pane.
|
||||
7. Copy reference + Pass-on-to-Agent (clipboard + bracketed-paste into the agent PTY).
|
||||
Reference in New Issue
Block a user