From 2e86a5ddeb0f50b6998f991e24d5f7d855d34136 Mon Sep 17 00:00:00 2001 From: Jared <865332676@qq.com> Date: Mon, 13 Jul 2026 11:17:44 +0800 Subject: [PATCH] fix(web): refine message sidebar interactions --- .../WorkspaceRows/WorkspaceRows.module.css | 35 ++---- .../WorkspaceRows/WorkspaceRows.tsx | 101 ++++-------------- .../WorkspaceSidebar/WorkspaceSidebar.tsx | 9 -- .../components/WorkspaceSidebar.test.tsx | 19 ++++ 4 files changed, 46 insertions(+), 118 deletions(-) diff --git a/web/app/src/pages/WorkspacePage/components/WorkspaceRows/WorkspaceRows.module.css b/web/app/src/pages/WorkspacePage/components/WorkspaceRows/WorkspaceRows.module.css index 17510cb2..bf997745 100644 --- a/web/app/src/pages/WorkspacePage/components/WorkspaceRows/WorkspaceRows.module.css +++ b/web/app/src/pages/WorkspacePage/components/WorkspaceRows/WorkspaceRows.module.css @@ -202,24 +202,6 @@ color: currentColor; } -.addTooltip { - position: fixed; - z-index: var(--z-tooltip); - max-width: 180px; - padding: 5px 8px; - border: 1px solid var(--gray-200); - border-radius: 6px; - background: var(--white); - color: var(--gray-700); - box-shadow: var(--shadow-sm); - font-family: var(--font-sans); - font-size: 12px; - font-weight: 500; - line-height: 18px; - pointer-events: none; - white-space: nowrap; -} - .groupItems { padding: 4px 8px 8px; display: grid; @@ -460,12 +442,17 @@ :global(:root[data-theme="dark"]) .sortable .groupHead:hover, :global(:root[data-theme="dark"]) .dragOver .groupHead, -:global(:root[data-theme="dark"]) .row:hover, -:global(:root[data-theme="dark"]) .active { - background: var(--panel-strong); +:global(:root[data-theme="dark"]) .row:hover { + background: var(--panel-soft); color: var(--gray-100); } +:global(:root[data-theme="dark"]) .row.active { + background: var(--gray-800); + color: var(--white); + box-shadow: none; +} + :global(:root[data-theme="dark"]) .groupToggle, :global(:root[data-theme="dark"]) .groupTitle, :global(:root[data-theme="dark"]) .groupTitle span { @@ -528,12 +515,6 @@ color: var(--gray-25); } -:global(:root[data-theme="dark"]) .addTooltip { - border-color: color-mix(in srgb, var(--white) 12%, transparent); - background: var(--gray-900); - color: var(--white); -} - @media (max-width: 720px) { .groupTitle, .groupTitle span { diff --git a/web/app/src/pages/WorkspacePage/components/WorkspaceRows/WorkspaceRows.tsx b/web/app/src/pages/WorkspacePage/components/WorkspaceRows/WorkspaceRows.tsx index 6871f293..a7b7611c 100644 --- a/web/app/src/pages/WorkspacePage/components/WorkspaceRows/WorkspaceRows.tsx +++ b/web/app/src/pages/WorkspacePage/components/WorkspaceRows/WorkspaceRows.tsx @@ -27,8 +27,6 @@ import { AgentAvatarContent } from "@/components/business/AgentAvatar"; import { avatarFallbackText } from "@/shared/avatar"; import { localizeRole } from "@/shared/i18n"; import { RoomAvatar, resolveRoomAvatarMembers } from "@/components/business/RoomAvatar"; -import { useEffect, useId, useRef, useState } from "react"; -import { createPortal } from "react-dom"; import { classNames } from "@/shared/lib/classNames"; import styles from "./WorkspaceRows.module.css"; import type { DragEvent, ReactNode } from "react"; @@ -64,86 +62,25 @@ export type WorkspaceGroupProps = { }; function WorkspaceAddAction({ icon, label, onAdd }: { icon: ReactNode; label: string; onAdd: () => void }) { - const triggerRef = useRef(null); - const tooltipId = useId(); - const [open, setOpen] = useState(false); - const [position, setPosition] = useState({ left: 0, top: 0 }); - - useEffect(() => { - if (!open) { - return undefined; - } - - function updatePosition() { - const trigger = triggerRef.current; - if (!trigger) { - return; - } - - const rect = trigger.getBoundingClientRect(); - const gap = 10; - const tooltipWidth = 180; - const tooltipHeight = 32; - const margin = 12; - const fitsRight = rect.right + gap + tooltipWidth <= window.innerWidth - margin; - const left = fitsRight ? rect.right + gap : Math.max(margin, rect.left - gap - tooltipWidth); - const top = Math.min( - window.innerHeight - tooltipHeight - margin, - Math.max(margin, rect.top + rect.height / 2 - tooltipHeight / 2), - ); - - setPosition({ left, top }); - } - - updatePosition(); - window.addEventListener("resize", updatePosition); - window.addEventListener("scroll", updatePosition, true); - return () => { - window.removeEventListener("resize", updatePosition); - window.removeEventListener("scroll", updatePosition, true); - }; - }, [open]); - return ( - <> - - {open - ? createPortal( - , - document.body, - ) - : null} - + ); } @@ -202,7 +139,7 @@ export function WorkspaceGroup({ {count} -
+
{onAdd ? ( } label={addLabel || title} onAdd={onAdd} /> ) : null} diff --git a/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspaceSidebar.tsx b/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspaceSidebar.tsx index 9361fc21..392e79e5 100644 --- a/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspaceSidebar.tsx +++ b/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspaceSidebar.tsx @@ -381,7 +381,6 @@ export function WorkspaceSidebar({ activeContextSectionId, onCreateAgent, onCreateNotificationParticipant, - onCreateRoom, onCreateModelProvider, onOpenCreateTeam, onOpenCreateTask, @@ -739,7 +738,6 @@ function contextCreateActionForSection({ hub, onCreateAgent, onCreateNotificationParticipant, - onCreateRoom, onCreateModelProvider, onOpenCreateTeam, onOpenCreateTask, @@ -751,7 +749,6 @@ function contextCreateActionForSection({ | "onCreateAgent" | "onCreateModelProvider" | "onCreateNotificationParticipant" - | "onCreateRoom" | "onOpenCreateScheduledTask" | "onOpenCreateTask" | "onOpenCreateTeam" @@ -762,12 +759,6 @@ function contextCreateActionForSection({ hub: WorkspaceSidebarProps["hub"]; setSkillUploadOpen: (open: boolean) => void; }) { - if (activeContextSectionId === WorkspaceContextSectionIds.messages) { - return { - label: t("createRoom"), - onClick: onCreateRoom, - }; - } if (activeContextSectionId === WorkspaceContextSectionIds.agents) { return { label: t("createAgent"), diff --git a/web/app/tests/components/WorkspaceSidebar.test.tsx b/web/app/tests/components/WorkspaceSidebar.test.tsx index 85bad050..d40c54cf 100644 --- a/web/app/tests/components/WorkspaceSidebar.test.tsx +++ b/web/app/tests/components/WorkspaceSidebar.test.tsx @@ -15,6 +15,7 @@ const labels: Record = { computerOverview: "Computer overview", computersSection: "Computers", configSettingsMenu: "Configuration", + createRoom: "Create room", directMessagesSection: "Direct messages", expandSidebar: "Expand sidebar", humanSection: "Human", @@ -169,6 +170,24 @@ function renderSidebar(overrides: Partial = {}) { } describe("WorkspaceSidebar", () => { + it("keeps room creation only in the Rooms section", () => { + const onCreateRoom = vi.fn(); + + renderSidebar({ + activePane: { type: WorkspacePaneTypes.conversation, id: "" }, + currentWorkspaceLabel: "Messages", + onCreateRoom, + workspaceTab: WorkspaceTabs.messages, + }); + + const createRoomButtons = screen.getAllByRole("button", { name: "Create room" }); + expect(createRoomButtons).toHaveLength(1); + expect(createRoomButtons[0].parentElement).toHaveAttribute("data-tooltip", "Create room"); + + fireEvent.click(createRoomButtons[0]); + expect(onCreateRoom).toHaveBeenCalledTimes(1); + }); + it("selects the MCP resource type when the MCP list is empty", () => { const onSelectMCPServer = vi.fn();