Skip to content

fix(wework): resolve composer and dialog display bugs - #2090

Closed
sdadunderscoresdad wants to merge 11 commits into
wecode-ai:mainfrom
sdadunderscoresdad:fix/ui-display-bugs-rerun
Closed

sdadunderscoresdad wants to merge 11 commits into
wecode-ai:mainfrom
sdadunderscoresdad:fix/ui-display-bugs-rerun

Conversation

@sdadunderscoresdad

@sdadunderscoresdad sdadunderscoresdad commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes a set of UI display bugs in the wework desktop client:

  • Model selector layout: menu now opens to the left and stays inside the available viewport, respecting the right workspace panel boundary instead of being clipped by it.
  • Embedded browser occlusion: only occlude the embedded browser when the cloud connection dialog is open, keeping it visible under normal overlays.
  • Cloud-work error popover: rendered via portal so it layers correctly, and closes on an outside click.
  • Dialog theming: removed forced dark mode from the add-device and cloud-work dialogs so they follow the active theme.
  • macOS input arrow keys: swallow arrow-key events at native input boundaries to prevent unintended composer navigation.
  • Narrow composer toolbar: cap the model selector trigger width and collapse the quick phrase menu to icon-only when the toolbar is narrow, preventing overlap/overflow.

Test plan

  • Open the desktop model selector and verify the menu is left-aligned and does not cross the right workspace panel edge.
  • Open the cloud connection dialog and confirm the embedded browser is occluded; close the dialog and confirm the browser is visible again.
  • Trigger a cloud-work error popover and click outside; it should close.
  • Open add-device / cloud-work dialogs in light theme and confirm they render in light mode.
  • In a native text input on macOS, press arrow keys at the start/end of the text and verify the cursor stays in the input.
  • Resize the composer to a narrow width and verify the quick phrase button shows only an icon and the model selector does not expand past its capped width.

Summary by CodeRabbit

  • New Features

    • Improved chat composer responsiveness with compact toolbar layouts and icon-only quick phrases.
    • Enhanced model selector sizing and positioning around workspace panels.
    • Improved cloud error details popover positioning, outside-click handling, and resizing behavior.
    • Prevented certain macOS desktop arrow-key input issues.
  • Bug Fixes

    • Improved embedded browser behavior when panels and cloud connection dialogs open or change.
    • Updated project and cloud dialogs to better follow application theme colors.

jiaqi62 and others added 10 commits July 20, 2026 18:15
Work around a WKWebView/Tauri bug (tauri-apps/tauri#5685) where pressing
ArrowLeft/ArrowRight at the start/end of a native text input leaks through
AppKit's insertText: path and inserts U+FFFC / tofu characters. The chat
composer uses ProseMirror and was not affected.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… occlusion to cloud dialog

Keep the embedded browser visible under normal overlays; only occlude it
when the cloud connection dialog is open so the dialog is not covered.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ialogs

Replace hardcoded dark colors in StandaloneProjectDialogs,
DeviceFolderPicker remoteDark variant, and AddCloudDeviceDialog
command block with semantic tokens so they follow the active theme.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…outside click

The cloud work unavailable error popover was clipped by the sidebar's
overflow-hidden wrapper. Render it through a portal with fixed positioning
anchored to the warning button so it displays fully outside the sidebar.

Also close the popover when clicking anywhere else on the page, while
keeping clicks on the trigger button or inside the popover from closing it.
Add tests for outside-click dismissal and inside-click persistence.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…arrow toolbar

Prevent the model selector trigger from expanding to 240px when opened in
a narrow composer toolbar by capping its width with maxClosedWidth. Also
switch the quick phrase menu to icon-only mode when the toolbar is narrow
so the right-side controls do not overlap or overflow.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The PR adds responsive composer controls, a macOS Tauri input arrow-key guard, portal-based cloud error details with embedded-browser occlusion handling, and theme-token styling updates for project and cloud dialogs.

Responsive composer layout

Layer / File(s) Summary
Toolbar compact controls
wework/src/components/chat/composer/ComposerToolbar.tsx, QuickPhraseMenu.tsx, ComposerToolbar.test.tsx, QuickPhraseMenu.test.tsx
Toolbar width observation controls icon-only quick phrases and narrower model-selector sizing.
Model selector boundaries and width contract
wework/src/components/chat/composer/ModelSelector.tsx, ModelSelectorTrigger.tsx, model-selector-types.ts, ModelSelector.test.tsx, ChatInput.test.tsx
Desktop menu positioning uses the workspace shell boundary, while trigger width is capped through --model-selector-width.

macOS input arrow-key guard

Layer / File(s) Summary
Guard implementation and validation
wework/src/lib/macosInputArrowKeyGuard.ts, wework/src/lib/macosInputArrowKeyGuard.test.ts, wework/src/App.tsx
The guard prevents eligible boundary arrow keys in Tauri macOS inputs and is installed from AppShell, with platform and input-state coverage.

Cloud overlay and embedded-browser behavior

Layer / File(s) Summary
Embedded-browser occlusion wiring
wework/src/hooks/useEmbeddedBrowserOcclusion.ts, wework/src/features/cloud-connection/CloudConnectionDialog.tsx, wework/src/components/layout/workspace-panels/WorkspaceBrowserPanel.tsx, tests
Dialog visibility synchronizes embedded-browser occlusion, and the browser-panel effect tracks its current label.
Cloud error portal positioning
wework/src/features/cloud-connection/CloudConnectionSidebarButton.tsx, wework/src/components/layout/DesktopSidebar.test.tsx
Cloud error details render in a positioned portal, update on resize, and close on outside pointer interaction.

Theme-token styling

Layer / File(s) Summary
Project and cloud dialog theme tokens
wework/src/components/projects/DeviceFolderPicker.tsx, wework/src/components/projects/StandaloneProjectDialogs.tsx, wework/src/components/settings/AddCloudDeviceDialog.tsx
Hard-coded dark-mode classes are replaced with theme-token classes across project and remote-command dialogs.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

Responsive composer layout

sequenceDiagram
  participant ComposerToolbar
  participant ResizeObserver
  participant QuickPhraseMenu
  participant ModelSelector
  ComposerToolbar->>ResizeObserver: observe toolbar width
  ResizeObserver-->>ComposerToolbar: report width
  ComposerToolbar->>QuickPhraseMenu: apply icon-only mode
  ComposerToolbar->>ModelSelector: apply narrow width cap
Loading

Cloud error details

sequenceDiagram
  participant User
  participant CloudConnectionSidebarButton
  participant document.body
  User->>CloudConnectionSidebarButton: open error details
  CloudConnectionSidebarButton->>CloudConnectionSidebarButton: calculate button position
  CloudConnectionSidebarButton->>document.body: render fixed portal
  User->>document.body: click outside popover
  document.body-->>CloudConnectionSidebarButton: close popover
Loading

Possibly related PRs

Suggested reviewers: qdaxb

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main focus on composer fixes and dialog display behavior changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
wework/src/components/layout/workspace-panels/WorkspaceBrowserPanel.tsx (1)

1259-1259: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove unused label dependency.

The label variable is not used within this useEffect block, so it does not need to be in the dependency array. Re-running this effect when label changes causes unnecessary teardown and recreation of the window event listeners.

♻️ Proposed fix
-  }, [label])
+  }, [])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/layout/workspace-panels/WorkspaceBrowserPanel.tsx` at
line 1259, Remove the unused label dependency from the useEffect dependency
array in the workspace panel component, leaving only values referenced by the
effect so window event listeners are not unnecessarily recreated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wework/src/components/projects/DeviceFolderPicker.tsx`:
- Around line 258-262: Add focus-within:border-text-secondary to the dark-mode
label wrapper in wework/src/components/projects/DeviceFolderPicker.tsx lines
258-262 and the remote-host span wrapper in
wework/src/components/projects/StandaloneProjectDialogs.tsx lines 581-588,
preserving their existing classes and conditional styling.

In `@wework/src/lib/macosInputArrowKeyGuard.ts`:
- Around line 32-39: Update the selection access in the macOS input arrow-key
guard to handle Safari/WKWebView InvalidStateError for unsupported input types.
Wrap reading selectionStart and selectionEnd in try/catch and return false when
the access throws, while preserving the existing arrow-key boundary logic for
supported inputs.

---

Nitpick comments:
In `@wework/src/components/layout/workspace-panels/WorkspaceBrowserPanel.tsx`:
- Line 1259: Remove the unused label dependency from the useEffect dependency
array in the workspace panel component, leaving only values referenced by the
effect so window event listeners are not unnecessarily recreated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1d11630a-1015-4710-abea-328064f662b0

📥 Commits

Reviewing files that changed from the base of the PR and between f512534 and d76b32f.

📒 Files selected for processing (21)
  • wework/src/App.tsx
  • wework/src/components/chat/ChatInput.test.tsx
  • wework/src/components/chat/composer/ComposerToolbar.test.tsx
  • wework/src/components/chat/composer/ComposerToolbar.tsx
  • wework/src/components/chat/composer/ModelSelector.test.tsx
  • wework/src/components/chat/composer/ModelSelector.tsx
  • wework/src/components/chat/composer/ModelSelectorTrigger.tsx
  • wework/src/components/chat/composer/QuickPhraseMenu.test.tsx
  • wework/src/components/chat/composer/QuickPhraseMenu.tsx
  • wework/src/components/chat/composer/model-selector-types.ts
  • wework/src/components/layout/DesktopSidebar.test.tsx
  • wework/src/components/layout/workspace-panels/WorkspaceBrowserPanel.test.tsx
  • wework/src/components/layout/workspace-panels/WorkspaceBrowserPanel.tsx
  • wework/src/components/projects/DeviceFolderPicker.tsx
  • wework/src/components/projects/StandaloneProjectDialogs.tsx
  • wework/src/components/settings/AddCloudDeviceDialog.tsx
  • wework/src/features/cloud-connection/CloudConnectionDialog.tsx
  • wework/src/features/cloud-connection/CloudConnectionSidebarButton.tsx
  • wework/src/hooks/useEmbeddedBrowserOcclusion.ts
  • wework/src/lib/macosInputArrowKeyGuard.test.ts
  • wework/src/lib/macosInputArrowKeyGuard.ts

Comment on lines 258 to 262
className={
dark
? 'min-w-0 flex-1 rounded-[10px] border border-[#555] bg-[#2b2b2b] px-3'
? 'min-w-0 flex-1 rounded-[10px] border border-border bg-background px-3'
: 'min-w-0 flex-1'
}

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Provide visual focus states for custom form controls.

The custom input and select wrappers lack visual focus indicators. Because the inner elements use outline-none to hide the default browser focus ring, their outer containers must provide an alternative state. Without this, keyboard users have no way to see when these fields are focused.

  • wework/src/components/projects/DeviceFolderPicker.tsx#L258-L262: Add focus-within:border-text-secondary to the dark mode label wrapper.
  • wework/src/components/projects/StandaloneProjectDialogs.tsx#L581-L588: Add focus-within:border-text-secondary to the remote host span wrapper.

As per coding guidelines, accessibility blockers such as missing focus states in forms must be fixed.

📍 Affects 2 files
  • wework/src/components/projects/DeviceFolderPicker.tsx#L258-L262 (this comment)
  • wework/src/components/projects/StandaloneProjectDialogs.tsx#L581-L588
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/projects/DeviceFolderPicker.tsx` around lines 258 -
262, Add focus-within:border-text-secondary to the dark-mode label wrapper in
wework/src/components/projects/DeviceFolderPicker.tsx lines 258-262 and the
remote-host span wrapper in
wework/src/components/projects/StandaloneProjectDialogs.tsx lines 581-588,
preserving their existing classes and conditional styling.

Source: Coding guidelines

Comment on lines +32 to +39
const { selectionStart, selectionEnd, value } = input
if (selectionStart === null || selectionEnd === null) return false
if (selectionStart !== selectionEnd) return false

if (event.key === ARROW_LEFT && selectionStart === 0) return true
if (event.key === ARROW_RIGHT && selectionEnd === value.length) return true
return false
}

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does accessing the selectionStart property on an HTML input element of type "number" or "email" throw an error in modern browsers?

💡 Result:

Yes, accessing the selectionStart property on an HTML input element of type number or email throws an InvalidStateError in modern browsers [1][2][3][4]. According to the HTML Standard, the selectionStart and selectionEnd properties—as well as methods like setSelectionRange—are only defined for input elements of specific types: text, search, url, tel, and password [3][5]. For other input types, such as number and email, browsers are required to throw an InvalidStateError when these properties or methods are accessed or invoked [1][3][4]. This restriction exists because these input types are intended to represent specialized controls rather than simple text fields. Consequently, the concept of a selection range (caret position or highlighted text) is not consistently supported or meaningful across different platforms and browser implementations for these types [1][6][7]. If you require selection functionality, the common workaround is to temporarily change the input type to text before performing the operation and then revert it back to the original type [4].

Citations:


🏁 Script executed:

sed -n '1,160p' wework/src/lib/macosInputArrowKeyGuard.ts

Repository: wecode-ai/Wegent

Length of output: 2092


Catch selectionStart access on unsupported input types.

selectionStart/selectionEnd throw InvalidStateError on inputs like type="number" or type="email" in Safari/WKWebView. Wrap the read in try...catch and return false for those elements.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/lib/macosInputArrowKeyGuard.ts` around lines 32 - 39, Update the
selection access in the macOS input arrow-key guard to handle Safari/WKWebView
InvalidStateError for unsupported input types. Wrap reading selectionStart and
selectionEnd in try/catch and return false when the access throws, while
preserving the existing arrow-key boundary logic for supported inputs.

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