Skip to content

Improves the CodeWhale VS Code sidebar and input experience - #8

Closed
eoli wants to merge 4 commits into
HengQuWorld:mainfrom
eoli:sidebar-input-box-all-in-one
Closed

eoli wants to merge 4 commits into
HengQuWorld:mainfrom
eoli:sidebar-input-box-all-in-one

Conversation

@eoli

@eoli eoli commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

This PR improves the CodeWhale VS Code sidebar and input experience.

Changes
Redesign the chat input as a bordered composer with a bottom toolbar.
Move the attachment button and send/stop button into the toolbar.
Replace text labels with inline SVG icons.
Add manual input resizing with persisted height.
Harden resize handling with rAF throttling, window-level listeners, and cleanup on mouseleave/blur.
Remove the previous auto-grow behavior to keep the input height stable while typing.
Move the configuration entry from the webview into the VS Code native sidebar title bar.
Add a native gear action to the view title.
Remove the redundant settings view and webview settings button.
Keep the existing /config command.
Remove the custom sidebar resize handle.
VS Code already provides native sidebar resizing.
The custom resize implementation could interfere with VS Code's native drag behavior, so the redundant handle and its associated code are removed.
Update and extend tests to cover the new input behavior, configuration contribution, and removed webview elements.
Sync package-lock.json to version 0.6.0.

- Delete #sidebar-resize-handle CSS, DOM node, drag script, and the
  related test assertions
- Harden the input resize drag: rAF throttling, window listeners, and
  cleanup on mouseleave/blur via body.is-resizing
- Skip tooltip repositioning while a resize drag is in progress
- Sync package-lock.json to version 0.6.0
The config panel was reachable through a gear button rendered inside the
chat webview. Move it into the editor chrome instead: the sidebar view
title bar now shows a small gear icon, and the webview no longer renders
any settings button.

- Contribute `brotherwhale.openConfig` with `"icon": "$(gear)"` and expose
  it through `menus["view/title"]` in the `navigation` group, scoped to
  `view == brotherwhale.chat`, so the action sits at the top of the
  CodeWhale sidebar panel
- Register the command in `extension.ts` to open `ConfigPanel`, keeping
  the command id in sync with the manifest
- Drop the redundant `brotherwhale.settings` tree view, its
  `SettingsViewProvider`, and the now-unused `views.settings.name` and
  `openConfigPanel` keys, so the gear becomes the single entry point
- Remove the `#btn-config` button from the webview along with its CSS
  block and its click handler
- Add `package-contributions.test.ts` to guard the gear contribution
  (command icon, menu placement, single view) and to keep `#btn-config`
  from creeping back into the webview sources

The `/config` slash command keeps opening the same panel.
The composer was a plain row of attach button, textarea, and Send/Stop
text buttons. Redesign it as a bordered input box whose bottom edge is a
toolbar: the attachment button starts from the left, a compact icon-only
send/stop button is pinned to the far right, and the textarea fills the
box above the toolbar.

- Wrap the textarea and an #input-toolbar in a bordered #input-box with
  a :focus-within highlight; the toolbar hosts #btn-attach on the left
  and #btn-send-stop on the right via margin-left: auto
- Replace the Send/Stop text labels with inline SVG icons (paper plane /
  square) since the webview does not load the codicon font; titles and
  aria-labels switch with the streaming state
- Keep the composer height under explicit user control: the textarea has
  a hard-coded 52px floor (about two rows above the 34px toolbar) and
  the resize handle drags the textarea itself between 52 and 340px,
  persisted as codewhale:inputHeight; overflowing text scrolls inside
  the box with the scrollbar hidden instead of resizing the composer
- Remove the previous auto-grow logic and its height resets on send and
  history recall, which made the frame jump while typing
- Size #input-box with flex: 1 0 auto so the frame always encloses the
  textarea plus the toolbar; the earlier flex: 1 + min-height: 0
  collapsed the border to zero and let text and the toolbar spill
  outside it
- Fix the stop state that never turned red in practice: the .streaming
  rule was outranked by the generic button background selector
- Extend the webview tests, including runtime tests that execute the
  input script against a real DOM to cover height behavior, send/stop
  icon toggling, and toolbar placement
@eoli

eoli commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author
Kapture 2026-09-16 at 17 30 51

@gaord

gaord commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Thanks for consolidating everything here — the composer redesign (textarea above a bottom toolbar, icon-only send/stop, focus ring) looks clean and is well covered by the new tests.

On the native-resizing argument for removing the sidebar handle, though, I have to push back with specifics, because I don't think it holds:

1. VS Code's native resize cannot widen the session list.
The native drag resizes the view container (the whole side panel hosting the webview). Our session list (#threads-panel) is a div inside the webview, and in this PR it is still width: 220px with default flex-grow: 0 (unchanged from main). So dragging the container edge only widens #chat-area; the threads panel stays exactly 220px, and its max-width: 600px becomes unreachable once the custom handle is gone. Unless we redesign the panel to flex-grow and fill the container — a different layout that would squeeze the chat area — native resizing can't replace the handle.

2. The "interference with native dragging" claim has no mechanism.
The custom handle lives inside the webview iframe (~220px from the left edge); the workbench's container sash is at the panel's outer edge, outside the iframe. A mousedown inside the iframe never reaches VS Code's sash drag logic, so the two can't compete. What was most likely observed as "interference" is the same stuck-drag bug this PR already fixes for the input handle: the old code bound listeners to document, which stops firing once the cursor leaves the iframe mid-drag, so the drag appears to die or get "taken over". That's a bug to fix, not a reason to remove the feature.

Requested change (same as on #5): restore #sidebar-resize-handle with the exact hardening pattern you applied to the input handle — window-level listeners, mouseleave/blur cleanup, rAF-throttled width writes — plus the codewhale:sidebarWidth persistence and its test assertions. Everything else in this PR (composer, native gear entry, tooltip skip, lockfile sync) is good to go from my side.

PS.
A quick test with trae and vscode turns out dragging sidebar not working any more with the pr. Other than that, it's a nice piece of work for better UI!

@eoli

eoli commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

Got it — I see now, there was a hidden menu there that I'd missed.

I'll look into improving this. I might end up moving it somewhere else instead.

- Restore #sidebar-resize-handle DOM node, CSS, and drag script so the
  threads panel can be resized inside the webview again
- Harden the sidebar drag like the input handle: window-level listeners,
  mouseleave/blur cleanup, rAF-throttled width writes, is-resizing guard
- Persist the sidebar width across sessions via codewhale:sidebarWidth
- Hide the handle while #threads-panel is collapsed so a closed sidebar
  never shows a dead grip
- Fix input handle cleanup so it removes the window listeners it registers
- Restore and extend test coverage: handle selectors, hardened drag
  pattern, script count, and collapsed-panel hiding
@eoli

eoli commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

I've added the sidebar-resize-handle back on #9.

I also fixed a related bug: previously, the handle would still show up at the far left even when the session panel wasn't open, which got in the way when users tried to resize the chat area.

@eoli eoli closed this Sep 16, 2026
@eoli
eoli deleted the sidebar-input-box-all-in-one branch September 16, 2026 14:14
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