5.2 KiB
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 Responseswhen partial,Send All Responseswhen 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-codeblock withfont-mono text-xs, max-height ~150px with overflow scroll
- Toggle:
- Done items are re-editable. Clicking anywhere on a completed (green) card reopens it in
activestate for editing. Cards getcursor-pointerand a subtle hover state (hover:border-success/40) to signal editability. This uses the existingupdateTask(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:
allHandledcheck on submit button changes from "all done/skipped" to "at least 1 done/skipped"handleSubmitsends only items that have statedoneorskipped- Items still in
pendingoractivestate are excluded from the submission payload
Submission logic in AssistantChatPage.tsx (handleTaskSubmit):
- No changes needed — it already formats based on
r.state === 'done'andr.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:
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:
<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). Subtletext-muted/40by default,text-muted-foregroundon hover. - Resize behavior:
onMouseDownon the grip starts trackingmousemoveondocumentupdates the widthmouseUpondocumentstops tracking- Width clamped between 280px min and 50vw max
cursor: col-resizeapplied to the grip and todocument.bodyduring drag (prevents cursor flicker)user-select: noneondocument.bodyduring drag (prevents text selection)
- Persistence: Width saved to
localStoragekeyrf-tasklane-width. Read on mount, written on drag end. Default:340px. - Implementation: All in
TaskLane.tsx— no external libraries. UsesuseReffor drag state (avoids re-renders during drag),useStatefor 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)