Skip to content

fix(chat): never block composer mid-round + auto-grow, popout z-index, harness icons, home→full-screen#207

Merged
rbuergi merged 3 commits into
mainfrom
fix/chat-composer-ux
Jul 2, 2026
Merged

fix(chat): never block composer mid-round + auto-grow, popout z-index, harness icons, home→full-screen#207
rbuergi merged 3 commits into
mainfrom
fix/chat-composer-ux

Conversation

@rbuergi

@rbuergi rbuergi commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Five chat-composer UX fixes reported during a live review.

Changes

  • Composer too small / lines scroll up (MonacoEditorView.razor.js) — auto-grow set an inline height on the inner .monaco-editor-view, but CSS pins that element to height:100% !important, which overrides an inline style — so the height was ignored and the box stayed at the 80px min-height while long input scrolled invisibly. Now sizes the outer .monaco-editor-container (holds the min/max clamps, no !important) and re-lays out.
  • Composer chronically blocked after a round (ThreadChatView.razor + .razor.cs) — the Send button and Enter path were gated on ThreadViewModel.IsExecuting, locking the composer for the whole round (only released when Status→Idle propagated / a watchdog fired). Removed the gate: Enter/Send work anytime, input clears on submit (the receipt ack), and a mid-round message queues via PendingUserMessages and runs when the round finishes. Esc still cancels; the 500 ms same-text dedup still guards double-sends.
  • Start chat from main screen → full-screen (ThreadSidePanelContent.razor.cs) — a new chat started from the root/home screen now navigates to /{threadPath} (the ApplicationPage catch-all) instead of opening in the side panel; a "+" new chat started inside the side panel keeps the in-panel behavior. The OpenThreadPath signal is consumed first so it can't re-navigate on return.
  • Harness icons blank/generic (MeshNodePickerView.razor.css) — Claude Code & Copilot embed their logo as an inline <svg> with a viewBox but no width/height, injected via MarkupString (no CSS-isolation scope). Unsized, it renders at the browser default (~300×150) and overflows/collapses. Added ::deep .mesh-node-picker-avatar svg { width:100%; height:100% }.
  • Side panel covers harness/model popout (MeshNodePickerView.razor.css) — the picker dropdown sat at z-index:10, under the side-panel header (10) and portal menu bar (1100). Lifted the dropdown to 10000 and its click-overlay to 9999 (the floating tier the slash-command palette already uses).

Verification

  • Built the touched project (MeshWeaver.Blazor.Portal) merged with current main under the exact CI flags — -c Release -p:CIRun=true -warnaserror0 warnings / 0 errors.

Note

If a harness still shows a generic bot glyph (not blank) after this, the harness nodes in that portal were seeded before the inline icons existed → stale data needing a re-seed, not this CSS.

🤖 Generated with Claude Code

rbuergi and others added 2 commits July 2, 2026 23:44
… harness icons, home→full-screen

Five chat-composer UX fixes:

- MonacoEditorView.razor.js: auto-grow now sizes the OUTER .monaco-editor-container. The inner
  .monaco-editor-view is pinned to `height:100% !important`, which overrode the inline height the
  auto-grow set on it, so the box stayed at the 80px min-height and long input scrolled invisibly.
  Sizing the outer container (which holds the min/max clamps, no !important) lets it grow with content.

- ThreadChatView.razor(.cs): remove the IsExecuting whole-round gate on Send + Enter. The composer
  no longer blocks while a round runs — a mid-round message is accepted immediately (echoed via
  PendingUserMessages) and drained when the round finishes; the input clears on submit. Esc still
  cancels the in-flight round; TryBeginSubmit still dedups an accidental double-submit.

- ThreadSidePanelContent.razor.cs: a new chat started from the main/home screen (root URL) now opens
  full-screen (/{threadPath}, the ApplicationPage catch-all) instead of the side panel; a "+" new
  chat started inside the side panel keeps the in-panel behavior. Signal consumed first so it can't
  re-navigate on return.

- MeshNodePickerView.razor.css: size inline avatar <svg> to fill the 28px box (unsized inline SVGs,
  injected via MarkupString, rendered at the browser default and read as blank/generic harness icons);
  lift the picker dropdown/overlay above app chrome (z-index 10000/9999) so the side-panel top bar no
  longer covers the harness/model popout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves the chat/composer UX in the Blazor portal by fixing composer sizing, removing execution-time input blocking, correcting navigation behavior when starting a new chat from the home screen, and addressing picker popout/icon rendering issues.

Changes:

  • Fix Monaco composer auto-grow by sizing the outer container and forcing a layout refresh.
  • Allow Enter/Send submissions while a round is executing (queueing via pending messages) and adjust send-button disabled/tooltip logic.
  • Update side-panel “new chat” navigation to open full-screen from the root page; raise picker dropdown z-index and constrain inline-SVG avatar sizing.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/MeshWeaver.Blazor/Components/Monaco/MonacoEditorView.razor.js Adjust auto-grow to resize the outer Monaco container and trigger layout.
src/MeshWeaver.Blazor/Components/MeshNodePickerView.razor.css Constrain inline SVG avatars and lift overlay/dropdown z-index to avoid chrome overlap.
src/MeshWeaver.Blazor.Portal/Chat/ThreadSidePanelContent.razor.cs Consume OpenThreadPath earlier and navigate to full-screen when invoked from the root URL.
src/MeshWeaver.Blazor.Portal/Chat/ThreadChatView.razor.cs Remove “IsExecuting” gating for Enter submission; rely on submit handler + queuing behavior.
src/MeshWeaver.Blazor.Portal/Chat/ThreadChatView.razor Remove “IsExecuting” from Send button disabled state and simplify tooltip text.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/MeshWeaver.Blazor/Components/Monaco/MonacoEditorView.razor.js
Comment thread src/MeshWeaver.Blazor.Portal/Chat/ThreadSidePanelContent.razor.cs Outdated
Comment thread src/MeshWeaver.Blazor.Portal/Chat/ThreadSidePanelContent.razor.cs Outdated
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Test Results (shard 3)

798 tests  ±0   690 ✅ ±0   2m 26s ⏱️ -4s
 13 suites ±0   108 💤 ±0 
 13 files   ±0     0 ❌ ±0 

Results for commit eb78aaa. ± Comparison against base commit ecb5c91.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Test Results (shard 2)

   15 files  ±  0     15 suites  ±0   5m 37s ⏱️ - 2m 6s
1 208 tests  - 145  1 205 ✅  - 145  3 💤 ±0  0 ❌ ±0 
1 217 runs   - 175  1 214 ✅  - 175  3 💤 ±0  0 ❌ ±0 

Results for commit eb78aaa. ± Comparison against base commit ecb5c91.

This pull request removes 145 tests.
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.AgenticAI.md")
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ChatCommands.md")
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ExecuteScript.md")
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ExecutiveAssistan"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.McpAuthentication"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ModelProviderSett"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ModelProviderSetu"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.PlatformProviderS"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ProviderConfigura"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.TeamsBot.md")
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Test Results (shard 0)

1 480 tests  ±0   1 480 ✅ ±0   3m 14s ⏱️ -15s
   12 suites ±0       0 💤 ±0 
   12 files   ±0       0 ❌ ±0 

Results for commit eb78aaa. ± Comparison against base commit ecb5c91.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Test Results (shard 1)

1 399 tests  +3   1 398 ✅ +3   6m 30s ⏱️ -4s
   14 suites ±0       1 💤 ±0 
   14 files   ±0       0 ❌ ±0 

Results for commit eb78aaa. ± Comparison against base commit ecb5c91.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Test Results

   54 files  ±  0     54 suites  ±0   17m 49s ⏱️ - 2m 28s
4 885 tests  - 142  4 773 ✅  - 142  112 💤 ±0  0 ❌ ±0 
4 894 runs   - 172  4 782 ✅  - 172  112 💤 ±0  0 ❌ ±0 

Results for commit eb78aaa. ± Comparison against base commit ecb5c91.

This pull request removes 145 and adds 3 tests. Note that renamed tests count towards both.
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.AgenticAI.md")
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ChatCommands.md")
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ExecuteScript.md")
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ExecutiveAssistan"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.McpAuthentication"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ModelProviderSett"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ModelProviderSetu"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.PlatformProviderS"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.ProviderConfigura"···)
MeshWeaver.Persistence.Test.DocumentationCodeBlockCompilationTest ‑ ExecutedCsharpBlocks_MustCompile(embeddedResourceName: "MeshWeaver.Documentation.Data.AI.TeamsBot.md")
…
MeshWeaver.Hosting.Monolith.Test.SlideLayoutAreaTest ‑ ContentArea_MiddleSlide_NavigatesOrderedSiblings
MeshWeaver.Hosting.Monolith.Test.SlideLayoutAreaTest ‑ PresentArea_IsChromeFree_WithClickableStage
MeshWeaver.Hosting.Monolith.Test.SlideLayoutAreaTest ‑ SlideContent_RoundTrips_WithShortTypeDiscriminator

♻️ This comment has been updated with latest results.

…ear failure, strip query/fragment

- MonacoEditorView.razor.js: guard editorInstance.layout() with getDomNode() — the editor can be
  disposed during the 50ms auto-grow debounce, and layout() then throws "Couldn't find the editor…".
- ThreadSidePanelContent.razor.cs: log (Warning) when clearing OpenThreadPath fails instead of
  swallowing it — a silent failure could leave the signal set and re-navigate on the next subscribe.
- ThreadSidePanelContent.razor.cs: strip query string / fragment before the root-URL "home" check so
  "/?x=1" or "/#y" still opens the new chat full-screen (ToBaseRelativePath keeps them).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rbuergi rbuergi merged commit 1f38440 into main Jul 2, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants