Summary
Three readability defects in the Workspace chat surface (/workspace), all in src/frontend/src/components/portal/PortalConversation.vue (and its twin PortalRoom.vue): message lines sit too tightly together, the message column uses only a narrow slice of the available panel width, and the composer renders a vertical scrollbar while it is empty.
Context
Reported from live use of the Workspace. The text reads "stuffy" — dense line spacing plus a narrow column — and the empty composer shows a scrollbar it has nothing to scroll.
1. Line spacing is too tight. The thread is space-y-4 with bubbles at px-3.5 py-2 text-sm, and the assistant's rendered markdown is squeezed further by the scoped rule .prose-portal :deep(p) { margin: 0.25rem 0; } — 4px between paragraphs, at the default text-sm leading. Needs a modest increase in line-height and inter-message/inter-paragraph rhythm (a tiny bit larger, not a redesign).
2. Message column is too narrow. Both the thread and the composer are capped at max-w-3xl mx-auto (48rem), and bubbles cap again at max-w-[85%] of that. On a wide viewport most of the panel is empty gutter. The column should take a higher percentage of the available panel width while staying readable.
3. Empty composer shows a vertical scrollbar. autoGrow() does:
el.style.height = 'auto'
el.style.height = Math.min(el.scrollHeight, 160) + 'px'
The textarea is box-sizing: border-box with a 1px border on each side (Tailwind border), and scrollHeight excludes borders — so the applied height is 2px short of the single line it must hold, and the browser shows a scrollbar even at zero characters. overflow-y is also never toggled to hidden below the max-h-40 ceiling. Reproduces after any input event that leaves the field empty (send, select-all-delete). The identical composer + autoGrow() exists in PortalRoom.vue, so any fix must land in both.
Acceptance Criteria
Technical Notes
- Files:
src/frontend/src/components/portal/PortalConversation.vue (thread max-w-3xl + space-y-4, composer textarea, autoGrow(), scoped .prose-portal block), src/frontend/src/components/portal/PortalRoom.vue (same composer and autoGrow())
- Scrollbar root cause: under
box-sizing: border-box, scrollHeight omits border width — the assigned height needs the border box accounted for (or the textarea needs overflow-y managed explicitly below the ceiling)
- Read
docs/memory/design-system-contract.md before touching any file under src/frontend/
- Raw-color ratchet:
node src/frontend/scripts/scan-raw-colors.mjs src/frontend must not regress per-file counts
Summary
Three readability defects in the Workspace chat surface (
/workspace), all insrc/frontend/src/components/portal/PortalConversation.vue(and its twinPortalRoom.vue): message lines sit too tightly together, the message column uses only a narrow slice of the available panel width, and the composer renders a vertical scrollbar while it is empty.Context
Reported from live use of the Workspace. The text reads "stuffy" — dense line spacing plus a narrow column — and the empty composer shows a scrollbar it has nothing to scroll.
1. Line spacing is too tight. The thread is
space-y-4with bubbles atpx-3.5 py-2 text-sm, and the assistant's rendered markdown is squeezed further by the scoped rule.prose-portal :deep(p) { margin: 0.25rem 0; }— 4px between paragraphs, at the defaulttext-smleading. Needs a modest increase in line-height and inter-message/inter-paragraph rhythm (a tiny bit larger, not a redesign).2. Message column is too narrow. Both the thread and the composer are capped at
max-w-3xl mx-auto(48rem), and bubbles cap again atmax-w-[85%]of that. On a wide viewport most of the panel is empty gutter. The column should take a higher percentage of the available panel width while staying readable.3. Empty composer shows a vertical scrollbar.
autoGrow()does:The textarea is
box-sizing: border-boxwith a 1px border on each side (Tailwindborder), andscrollHeightexcludes borders — so the applied height is 2px short of the single line it must hold, and the browser shows a scrollbar even at zero characters.overflow-yis also never toggled tohiddenbelow themax-h-40ceiling. Reproduces after any input event that leaves the field empty (send, select-all-delete). The identical composer +autoGrow()exists inPortalRoom.vue, so any fix must land in both.Acceptance Criteria
max-h-40ceilingPortalConversation.vueandPortalRoom.vue(same code, two files)docs/memory/design-system-contract.md— no raw Tailwind palette classes, no hardcoded hex; verified in light and darkTechnical Notes
src/frontend/src/components/portal/PortalConversation.vue(threadmax-w-3xl+space-y-4, composer textarea,autoGrow(), scoped.prose-portalblock),src/frontend/src/components/portal/PortalRoom.vue(same composer andautoGrow())box-sizing: border-box,scrollHeightomits border width — the assigned height needs the border box accounted for (or the textarea needsoverflow-ymanaged explicitly below the ceiling)docs/memory/design-system-contract.mdbefore touching any file undersrc/frontend/node src/frontend/scripts/scan-raw-colors.mjs src/frontendmust not regress per-file counts