diff --git a/desktop/src/features/profile/ui/ProfilePopover.tsx b/desktop/src/features/profile/ui/ProfilePopover.tsx index 5f98e9fb5..1e43ee2d5 100644 --- a/desktop/src/features/profile/ui/ProfilePopover.tsx +++ b/desktop/src/features/profile/ui/ProfilePopover.tsx @@ -121,7 +121,7 @@ export function ProfilePopover({ { @@ -277,10 +277,7 @@ export function ProfilePopover({ <>
{/* ── Workspace / relay selector ─────────────────── */} -
+
{workspaceSwitcherSlot}
diff --git a/desktop/src/features/sidebar/ui/SidebarProfileCard.tsx b/desktop/src/features/sidebar/ui/SidebarProfileCard.tsx index fcf489836..a0401eb72 100644 --- a/desktop/src/features/sidebar/ui/SidebarProfileCard.tsx +++ b/desktop/src/features/sidebar/ui/SidebarProfileCard.tsx @@ -54,10 +54,19 @@ export function SidebarProfileCard({ [], ); const hasStatus = Boolean(selfUserStatus?.text || selfUserStatus?.emoji); + const workspaceLabel = activeWorkspace?.name ?? "No workspace"; + const readonlyWorkspaceLabel = ( + + + {workspaceLabel} + + ); return (
@@ -132,7 +141,7 @@ export function SidebarProfileCard({
) : ( -
- -
+
{readonlyWorkspaceLabel}
)}
diff --git a/desktop/src/features/workspaces/ui/WorkspaceSwitcher.tsx b/desktop/src/features/workspaces/ui/WorkspaceSwitcher.tsx index 9970b1a2f..43cd7b8d8 100644 --- a/desktop/src/features/workspaces/ui/WorkspaceSwitcher.tsx +++ b/desktop/src/features/workspaces/ui/WorkspaceSwitcher.tsx @@ -21,6 +21,7 @@ import { SidebarMenuButton, SidebarMenuItem, } from "@/shared/ui/sidebar"; +import { Popover, PopoverContent, PopoverTrigger } from "@/shared/ui/popover"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/shared/ui/tooltip"; import type { ConnectionState } from "@/shared/api/relayClientShared"; import { @@ -63,11 +64,48 @@ export function WorkspaceSwitcher({ const [editingWorkspace, setEditingWorkspace] = React.useState(null); const [dropdownOpen, setDropdownOpen] = React.useState(false); + const profileMenuHoverTimer = React.useRef(null); const connectionState = useRelayConnection(); const degraded = isRelayConnectionDegraded(connectionState); const connectionLabel = CONNECTION_STATE_LABEL[connectionState]; const isProfileLike = variant === "profile" || variant === "profile-menu"; + function clearProfileMenuHoverTimer() { + if (profileMenuHoverTimer.current !== null) { + window.clearTimeout(profileMenuHoverTimer.current); + profileMenuHoverTimer.current = null; + } + } + + function scheduleProfileMenu(nextOpen: boolean) { + if (variant !== "profile-menu") return; + clearProfileMenuHoverTimer(); + profileMenuHoverTimer.current = window.setTimeout( + () => setDropdownOpen(nextOpen), + nextOpen ? 80 : 160, + ); + } + + function handleProfileMenuOpenChange(nextOpen: boolean) { + if (variant !== "profile-menu") { + setDropdownOpen(nextOpen); + return; + } + if (!nextOpen) { + clearProfileMenuHoverTimer(); + } + setDropdownOpen(nextOpen); + } + + React.useEffect( + () => () => { + if (profileMenuHoverTimer.current !== null) { + window.clearTimeout(profileMenuHoverTimer.current); + } + }, + [], + ); + const triggerContent = ( <> {variant === "profile-menu" ? null : degraded ? ( @@ -124,6 +162,92 @@ export function WorkspaceSwitcher({ ); + const profileMenuPopover = + variant === "profile-menu" ? ( + + + + + scheduleProfileMenu(true)} + onMouseLeave={() => scheduleProfileMenu(false)} + side="right" + sideOffset={0} + > +
+ {workspaces.map((workspace) => ( +
+ + +
+ ))} +
+ +
+ + + ) : null; + const switcherDropdown = ( @@ -163,13 +287,7 @@ export function WorkspaceSwitcher({ align="start" className="w-(--radix-dropdown-menu-trigger-width) min-w-[220px]" onCloseAutoFocus={(e) => e.preventDefault()} - side={ - variant === "profile-menu" - ? "right" - : variant === "profile" - ? "top" - : "bottom" - } + side={variant === "profile" ? "top" : "bottom"} sideOffset={4} > {workspaces.map((workspace) => ( @@ -214,6 +332,8 @@ export function WorkspaceSwitcher({ <> {variant === "profile" ? ( switcherDropdown + ) : variant === "profile-menu" ? ( + profileMenuPopover ) : ( {switcherDropdown}