docs: TaskLane improvements design spec and implementation plan

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-03-26 19:53:23 +00:00
parent ca60b77d9a
commit 37d217b12a
2 changed files with 689 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
# TaskLane Improvements Design
> **Date:** 2026-03-26
> **Status:** Approved
> **Scope:** `frontend/src/components/assistant/TaskLane.tsx`, `frontend/src/pages/AssistantChatPage.tsx`
---
## Context
The TaskLane is a right-side panel in the AI Assistant chat that renders structured questions and diagnostic actions from the AI. It launched with a working parse → render → submit pipeline, but has four UX issues and a missing submission flow design.
## Changes
### 1. Progressive Preview + Batch Submit
**Problem:** The "Send All Responses" button is disabled until every item is answered or skipped. Engineers often want to submit partial results — answer 2 of 3 questions, paste output from 1 of 4 commands, and let the AI work with what they have.
**Design:**
- **Submit enabled when ≥1 item is done or skipped.** Remaining pending items are simply omitted from the message (not auto-skipped — they're just not addressed).
- **Dynamic submit label:** `Send 2 of 6 Responses` when partial, `Send All Responses` when all handled.
- **Collapsible preview section** above the submit button:
- Toggle: `▶ Preview (2/6 done)` — collapsed by default
- Expands to show the formatted markdown message that will be sent to the AI
- Updates in real-time as items are answered/skipped
- Uses the same formatting logic as `handleTaskSubmit` (question answers in blockquotes, command output in code fences, skipped items noted)
- Styled as a `bg-code` block with `font-mono text-xs`, max-height ~150px with overflow scroll
- **Done items are re-editable.** Clicking anywhere on a completed (green) card reopens it in `active` state for editing. Cards get `cursor-pointer` and a subtle hover state (`hover:border-success/40`) to signal editability. This uses the existing `updateTask(idx, { state: 'active' })` mechanism — no new logic needed, just making the done card itself a click target.
- **No change to the TaskLane header or pending/active card behavior.** Changes affect the footer area and done card interactivity.
**Submission logic changes in `TaskLane.tsx`:**
- `allHandled` check on submit button changes from "all done/skipped" to "at least 1 done/skipped"
- `handleSubmit` sends only items that have state `done` or `skipped`
- Items still in `pending` or `active` state are excluded from the submission payload
**Submission logic in `AssistantChatPage.tsx` (`handleTaskSubmit`):**
- No changes needed — it already formats based on `r.state === 'done'` and `r.state === 'skipped'`, ignoring pending items.
### 2. TaskLane Reset on New Chat
**Problem:** Starting a new chat via `handleNewChat` doesn't clear the TaskLane. The previous session's questions/actions persist visually.
**Fix:** Add three lines to `handleNewChat` in `AssistantChatPage.tsx`:
```typescript
setShowTaskLane(false)
setActiveQuestions([])
setActiveActions([])
```
Same pattern already exists in `handleTaskSubmit`. Also add to `selectChat` for switching between chats.
### 3. Conditional Chat Input Border
**Problem:** The chat input area has `border-t border-border` which creates a double-border effect alongside the TaskLane footer's `border-t border-default`.
**Fix:** Conditionally remove the chat input's top border when the TaskLane is open:
```tsx
<div className={cn("px-3 sm:px-6 py-3 shrink-0", !showTaskLane && "border-t border-border")}>
```
The TaskLane's own left border and footer border provide sufficient visual separation when the panel is open. When closed, the chat input border returns.
### 4. Resizable TaskLane with Grip Handle
**Design:**
- **Drag zone:** 6px wide hit target on the left edge of the TaskLane, absolutely positioned.
- **Grip indicator:** Centered vertically on the drag zone — a 2×3 grid of small dots (6 dots total, `w-1 h-1 rounded-full bg-current`). Subtle `text-muted/40` by default, `text-muted-foreground` on hover.
- **Resize behavior:**
- `onMouseDown` on the grip starts tracking
- `mousemove` on `document` updates the width
- `mouseUp` on `document` stops tracking
- Width clamped between **280px** min and **50vw** max
- `cursor: col-resize` applied to the grip and to `document.body` during drag (prevents cursor flicker)
- `user-select: none` on `document.body` during drag (prevents text selection)
- **Persistence:** Width saved to `localStorage` key `rf-tasklane-width`. Read on mount, written on drag end. Default: `340px`.
- **Implementation:** All in `TaskLane.tsx` — no external libraries. Uses `useRef` for drag state (avoids re-renders during drag), `useState` for the width value.
**CSS change:** Replace `w-[340px]` with `style={{ width: panelWidth }}` on the outer div. Keep `shrink-0` so the chat area flexes.
---
## Files Modified
| File | Change |
|------|--------|
| `frontend/src/components/assistant/TaskLane.tsx` | Preview section, submit logic, resize handle, width persistence |
| `frontend/src/pages/AssistantChatPage.tsx` | TaskLane reset in `handleNewChat`/`selectChat`, conditional border |
## Out of Scope
- TaskLane rendering when loading historical sessions (markers are stripped from stored messages — no TaskLane on reload)
- Mobile-specific TaskLane layout (current: hidden on mobile, which is acceptable for now)
- Keyboard accessibility for resize handle (future enhancement)