Right-clicking a project card (or pressing the Menu key / Shift+F10 on a focused card) opens a workspace menu:
Add to workspace when the project belongs to none, Move to workspace when it already has one.
The current workspace is checked and disabled; the target list marks every workspace that already holds a member with the project's display name, because the backend rejects duplicate display names.
Home-directory projects stay isolated from workspace sharing (a workspace member must not be the user's home): the entry stays visible, disabled, with the reason in place — hiding it would look like a missing feature.
A failed save shows the backend's message; a failed move restores the previous membership when it can, and says so plainly when it cannot.
ProjectCard gains is_home_project, computed from the same check apply_workspace_changes uses, so the menu never offers an assignment the backend will refuse.
Known limitation
A move is a leave followed by a join, in that order — workspace_members.project_path is unique, so the two writes cannot run together and there is no single command for the pair. If the join fails and the restore also fails, the project ends up in no workspace, and the menu says exactly that ("It has left its old workspace and is now in none."). Making it atomic means a new backend command with its own contract; that felt out of scope for this issue.
Reuse
FloatingLayer was ConfigEditor-only and is now components/shared/FloatingLayer with an optional point placement, so the context menu opens at the pointer, dismisses the click that closed it, and closes on page scroll — without a second portal.
Verification
bun test src — 208 pass (adds workspace-menu-options.test.ts, 10 cases)
bunx biome check src, bunx tsc --noEmit
cargo fmt --check, cargo clippy --all-targets -D warnings, cargo test (adds 4 is_home_project tests; the 4 serve:: failures are the pre-existing local-proxy 502, same on clean master)
Manual: local --serve with a copy of a real database — both themes, keyboard focus return on Esc, disabled rows, the duplicate-name reason, and an actual add + move via the menu.
Summary by cubic
Right-clicking a project card—or pressing Menu or Shift+F10—opens an option to add it to a workspace or move it from its current workspace.
The current workspace, home-directory projects, and duplicate-name targets are disabled with their reason shown.
Moves leave the current workspace before joining the target; a failed join restores the old membership when possible, and the refreshed workspace list decides the error message.
Saves that only change membership or rename keep the stored share categories; the Workspaces panel sends categories only after a checkbox is toggled.
FloatingLayer now supports pointer placement, and the menu and error banner meet WCAG AA contrast in both themes.
The PR appears safe to merge; no new actionable issues were found.
Summary
Adds a project-card menu for adding or moving projects between workspaces.
Project cards open a menu to add or move a project between workspaces.
Workspace saves change sharing categories only after someone edits them.
Both earlier, unnumbered findings are fixed: membership writes no longer resend sharing settings, and clicking the opening card dismisses the menu without opening the project.