feat(web): stabilize and drag-reorder workspaces in the sidebar#1047
Conversation
🦋 Changeset detectedLatest commit: b74c3f3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3b8c92ebdc
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| () => { | ||
| const next = reconcileWorkspaceOrder( | ||
| mergedWorkspaces.value.map((w) => w.id), | ||
| workspaceOrder.value, |
There was a problem hiding this comment.
Preserve empty workspaces while reconciling order
On refresh, this watcher can run after the session list is populated but before loadWorkspaces() returns, so mergedWorkspaces only contains workspaces derived from sessions. If the persisted order includes a registered workspace with no sessions, reconcileWorkspaceOrder() treats that id as deleted and saves an order without it; when the workspace API later adds it back, it is considered newly seen and is prepended, so empty workspaces jump to the front instead of preserving the user's saved drag order. Gate the drop/removal reconciliation until the real workspace list has loaded, or avoid deleting stored ids during the derived-only phase.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8b93aeeb4d
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (fromIdx === -1 || toIdx === -1 || fromIdx === toIdx) return order; | ||
| const next = [...order]; | ||
| next.splice(fromIdx, 1); | ||
| next.splice(toIdx, 0, fromId); |
There was a problem hiding this comment.
Adjust downward drops to match the insertion marker
When dragging a workspace downward, toIdx is computed before fromId is removed, so the target shifts left and this inserts the source after the highlighted target. For example, dragging a over c in [a,b,c,d] produces [b,c,a,d], while the sidebar shows .drop-before at the top of c; users cannot trust the insertion marker. Adjust the insertion index after removing the source when fromIdx < toIdx (or recompute it) so the persisted order matches the drop indicator.
Useful? React with 👍 / 👎.
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f5d9220c4f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| @dragover="onGroupDragOver($event, g.workspace.id)" | ||
| @drop="onGroupDrop(g.workspace.id)" |
There was a problem hiding this comment.
Add an end-of-list drop target
With the current wiring every valid drop is tied to an existing workspace id and moveInOrder always inserts the dragged workspace before that target. In a list like [A, B, C], dragging A onto C yields [B, A, C], so there is no single drop position that can produce [B, C, A]; the new drag-reorder UI cannot move a workspace directly to the bottom. Add an after-last/bottom drop zone or distinguish before/after based on pointer position.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
When rawState.activeWorkspaceId is missing or stale (for example after the active workspace is removed, or when there is no persisted active workspace), this computed still falls back to mergedWorkspaces.value[0]. The new drag order is only applied in workspacesView, so the highlighted/default workspace can differ from the first visible group; actions such as the sidebar New Chat use client.activeWorkspaceId and can create the session in the daemon's first workspace instead of the user's reordered top workspace. Drive this fallback from the ordered workspace list as well.
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 85ae77cc03
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| })), | ||
| ); | ||
| })); | ||
| return sortByWorkspaceOrder(views, workspaceOrder.value); |
There was a problem hiding this comment.
Honor drag order when selecting the next workspace
When a user has a custom order and removes the active workspace, the removal paths still choose mergedWorkspaces.value[0] rather than this sorted workspacesView. For example, with daemon order A,B,C and dragged order C,B,A, removing C makes A active even though B is now the first visible group; the next-workspace fallback should use the same ordered view (or an injected ordered helper) so deletion does not jump back to daemon order.
Useful? React with 👍 / 👎.
|
Codex Review: Didn't find any major issues. Chef's kiss. Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
Related Issue
No related issue — UX polish requested directly.
Problem
The web sidebar's workspace order followed the daemon's list order, which shifts with recent activity, so workspaces kept moving around. There was no way to pin a preferred arrangement, and a page reload could reshuffle everything. Sessions within a group already reorder live by latest activity; workspaces did not have a stable equivalent.
What changed
Workspaces now keep a stable, locally-persisted order and can be reordered by dragging a group header.
kimi-web.workspace-orderholds the desired workspace id order (loadWorkspaceOrder/saveWorkspaceOrder).workspacesViewis sorted by that order, so the sidebar, mobile switcher and sessions dialog all reflect it. A watcher reconciles the stored order with the known workspace set: removed workspaces are dropped and newly-seen ones are prepended (newest first, the closest signal to a creation time, since workspaces carry nocreatedAt). The watcher keys on the id set, so a pure daemon reorder of the same workspaces no longer reshuffles the UI, and a drag reorder does not re-trigger it.reorderWorkspacesaction.updatedAtand reorder live as activity arrives.reconcileWorkspaceOrder,sortByWorkspaceOrder,moveInOrder) is factored intosrc/lib/workspaceOrder.tsfor unit testing.Checklist
workspace-order.test.ts, plus storage round-trip tests).gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update. (No user-facing docs to update for this behavior.)