# 2026-07-21 Chat window full polish

**Status:** Implemented. Streaming affordance, inline tool rendering, message
timestamps, code-copy buttons, and per-session store isolation all landed in
`web/src/lib/components/ChatThread.svelte` + the chat stores (v0.8.x–0.10.x).

## Context

After fixing the streaming reactivity bug and merging the double thinking
indicator, the chat window still has structural UX gaps: no streaming
affordance while text flows, tools never rendered inline, no timestamps,
no code copy, cross-session store leaks in floating windows, and minor
overflow/style holes.

## Decisions

| Question | Answer |
|---|---|
| Streaming feel | Typing cursor (blinking ▍) + inline indicator |
| Tool calls | Expandable inline tool cards in message flow |
| Empty state | Minimal — title + tagline, no suggestions |
| Dark theme | Keep neutral (skip) |
| Scope | Full polish — everything |

## Changes

### P0.1 Streaming cursor
- **File:** `web/src/lib/components/ChatThread.svelte`
- Add a blinking block-cursor (▍) appended after rendered markdown when
  `streaming` is true and the last assistant message has text.
- Keep the inline spinner + activity label for the empty-text state.
- CSS: `@keyframes` blink, `0.8s` cycle, `primary` color, `inline-block`.

### P0.2 Tool call cards
- **New:** `web/src/lib/components/ToolCallCard.svelte`
- **Modify:** `ChatThread.svelte`
- Render `msg.tools` as collapsible cards between text blocks.
- Collapsed: tool icon + name + status (running/done/error).
- Expanded: pretty-printed args + result/error in `pre` blocks.
- Keep it minimal — one card per tool call, no grouping.
- Wire `pendingApprovals` from `msg.pendingApprovals` as approval
  cards below the tool list.

### P1.3 Timestamps + role labels
- **Modify:** `ChatThread.svelte`, `ChatMessage` interface
- Add `created_at?: string` to `ChatMessage` (populated from `Message.created_at`).
- Show small muted timestamp (HH:MM) on hover or inline next to role label.
- Add tiny "You" / "Nomos" labels above bubbles (subtle, muted).

### P1.4 Code copy button
- **Modify:** `ChatThread.svelte` prose styles
- Wrap `pre` blocks in a relative container; add a copy button
  (clipboard icon, top-right, opacity-0 → visible on hover).
- Use `navigator.clipboard.writeText`.

### P1.5 Table overflow + user bubble fix
- **Modify:** `ChatThread.svelte` prose styles
- Wrap tables in `overflow-x-auto` container.
- Add `overflow-wrap: break-word` to user bubbles.

### P2.6 Cross-session fixes
- **Modify:** `web/src/lib/stores/chat.ts`, `SessionChatWindow.svelte`
- `chatErrors`: keep global for now (session-scoped errors are rare
  and the dismiss is manual anyway).
- `activityLog`: **per-session** — the store in `activity.ts` already
  derives from messages; make `computeActivityLog` session-scoped
  so each floating window only sees its own activity.

### P2.7 Min window size
- **Modify:** `web/src/lib/stores/windows.ts` (openTaskWindow)
- Add `minWidth: 600, minHeight: 400` to chat window open call.

### P2.8 Cleanup
- Delete `web/src/lib/components/AgentIndicator.svelte` (dead code).
- Update stale comments in `SessionChatWindow.svelte` and
  `TaskContextPanel.svelte` that reference a "main Chat page."
- Fix prose heading hierarchy: h1 = 1.15em, h2 = 1.1em, h3 = 1.05em.

## Verification

- `npx eslint` on all changed files
- `go vet ./cmd/nomos/...`
- `go build -o /dev/null ./cmd/nomos/...`
