From 4034036adfbe531175b670aae01672435d08549b Mon Sep 17 00:00:00 2001 From: youngbeom Date: Mon, 13 Jul 2026 15:19:58 +0800 Subject: [PATCH 1/2] fix(web): restore normal app scale --- .../ProfilePreviewPopover.tsx | 24 +++++++------------ .../WorkspacePrimaryNavigation.tsx | 14 +++++++---- web/app/src/shared/styles/globals.css | 19 --------------- .../components/ProfilePreviewPopover.test.tsx | 24 +++++++------------ web/app/tests/shared/appScale.test.ts | 14 +++++------ 5 files changed, 31 insertions(+), 64 deletions(-) diff --git a/web/app/src/pages/WorkspacePage/components/ProfilePreviewPopover/ProfilePreviewPopover.tsx b/web/app/src/pages/WorkspacePage/components/ProfilePreviewPopover/ProfilePreviewPopover.tsx index efea21dd..f2eb65fb 100644 --- a/web/app/src/pages/WorkspacePage/components/ProfilePreviewPopover/ProfilePreviewPopover.tsx +++ b/web/app/src/pages/WorkspacePage/components/ProfilePreviewPopover/ProfilePreviewPopover.tsx @@ -23,35 +23,27 @@ function clamp(value: number, min: number, max: number): number { return Math.min(max, Math.max(min, value)); } -function rootZoomScale(): number { - const zoom = Number.parseFloat(window.getComputedStyle(document.documentElement).zoom); - return Number.isFinite(zoom) && zoom > 0 ? zoom : 1; -} - function profilePreviewStyle(anchorRect: ProfilePreviewAnchorRect | null | undefined, cardHeight?: number | null) { - const scale = rootZoomScale(); const offset = 12; const viewportPadding = 16; - const width = Math.min(360, (window.innerWidth - viewportPadding * 2) / scale); - const visualWidth = width * scale; - const maxLeft = Math.max(viewportPadding, window.innerWidth - viewportPadding - visualWidth); - const visualCardHeight = cardHeight ?? 420 * scale; - const visibleHeight = Math.min(visualCardHeight, window.innerHeight - viewportPadding * 2); + const width = Math.min(360, window.innerWidth - viewportPadding * 2); + const maxLeft = Math.max(viewportPadding, window.innerWidth - viewportPadding - width); + const visibleHeight = Math.min(cardHeight ?? 420, window.innerHeight - viewportPadding * 2); const maxTop = Math.max(viewportPadding, window.innerHeight - viewportPadding - visibleHeight); if (!anchorRect) { return { - top: `${viewportPadding / scale}px`, - left: `${viewportPadding / scale}px`, + top: `${viewportPadding}px`, + left: `${viewportPadding}px`, width: `${width}px`, }; } - const hasRoomRight = anchorRect.right + offset + visualWidth <= window.innerWidth - viewportPadding; - const preferredLeft = hasRoomRight ? anchorRect.right + offset : anchorRect.left - visualWidth - offset; + const hasRoomRight = anchorRect.right + offset + width <= window.innerWidth - viewportPadding; + const preferredLeft = hasRoomRight ? anchorRect.right + offset : anchorRect.left - width - offset; const left = clamp(preferredLeft, viewportPadding, maxLeft); const top = clamp(anchorRect.top - 12, viewportPadding, maxTop); - return { top: `${top / scale}px`, left: `${left / scale}px`, width: `${width}px` }; + return { top: `${top}px`, left: `${left}px`, width: `${width}px` }; } export function ProfilePreviewPopover({ diff --git a/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspacePrimaryNavigation.tsx b/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspacePrimaryNavigation.tsx index d89fa9ca..6d548952 100644 --- a/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspacePrimaryNavigation.tsx +++ b/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspacePrimaryNavigation.tsx @@ -1,6 +1,7 @@ import { classNames } from "@/shared/lib/classNames"; import styles from "./WorkspaceSidebar.module.css"; import { useCallback, useId, useRef, useState } from "react"; +import { createPortal } from "react-dom"; import type { CSSProperties, ReactNode } from "react"; import type { WorkspaceContextSectionId } from "./types"; @@ -101,11 +102,14 @@ function PrimaryNavigationButton({ {typeof item.badge === "number" ? ( {formatBadge(item.badge)} ) : null} - {collapsed && tooltipStyle ? ( - - {item.label} - - ) : null} + {collapsed && tooltipStyle + ? createPortal( + + {item.label} + , + document.body, + ) + : null} ); } diff --git a/web/app/src/shared/styles/globals.css b/web/app/src/shared/styles/globals.css index cda64e16..f8cbd922 100644 --- a/web/app/src/shared/styles/globals.css +++ b/web/app/src/shared/styles/globals.css @@ -13,25 +13,6 @@ --app-ui-viewport-height: 100dvh; } -@supports (zoom: 80%) { - :root { - --app-ui-viewport-height: 125dvh; - --text-xs-size: 13px; - --text-sm-size: 15px; - --text-md-size: 17px; - --text-lg-size: 19px; - --text-xl-size: 21px; - --text-2xl-size: 25px; - --text-3xl-size: 31px; - --text-4xl-size: 37px; - --text-5xl-size: 49px; - --text-6xl-size: 61px; - --text-7xl-size: 73px; - font-size-adjust: 0.65; - zoom: 80%; - } -} - html, body, #root { diff --git a/web/app/tests/components/ProfilePreviewPopover.test.tsx b/web/app/tests/components/ProfilePreviewPopover.test.tsx index b6136540..4c9e3f50 100644 --- a/web/app/tests/components/ProfilePreviewPopover.test.tsx +++ b/web/app/tests/components/ProfilePreviewPopover.test.tsx @@ -34,12 +34,10 @@ function t(key: string): string { } describe("ProfilePreviewPopover", () => { - it("keeps the preview outside its anchor when the page is zoomed", () => { - const previousZoom = document.documentElement.style.zoom; - document.documentElement.style.zoom = "0.8"; + it("keeps the preview outside its anchor in normal viewport coordinates", () => { const anchorRect = { top: 120, right: 502, bottom: 152, left: 470 }; - const view = render( + render( ()} agent={{ id: "agent-1", name: "Builder", role: "worker", status: "running" }} @@ -52,19 +50,13 @@ describe("ProfilePreviewPopover", () => { />, ); - try { - const preview = screen.getByRole("dialog", { name: "Profile preview" }); - const scale = 0.8; - const visualLeft = Number.parseFloat(preview.style.left) * scale; - const visualTop = Number.parseFloat(preview.style.top) * scale; + const preview = screen.getByRole("dialog", { name: "Profile preview" }); + const left = Number.parseFloat(preview.style.left); + const top = Number.parseFloat(preview.style.top); - expect(visualLeft).toBe(anchorRect.right + 12); - expect(visualTop).toBe(anchorRect.top - 12); - expect(visualLeft).toBeGreaterThan(anchorRect.right); - } finally { - view.unmount(); - document.documentElement.style.zoom = previousZoom; - } + expect(left).toBe(anchorRect.right + 12); + expect(top).toBe(anchorRect.top - 12); + expect(left).toBeGreaterThan(anchorRect.right); }); it("shows compact agent runtime/provider/model fields with reasoning in model", () => { diff --git a/web/app/tests/shared/appScale.test.ts b/web/app/tests/shared/appScale.test.ts index 5053e30a..1a32c792 100644 --- a/web/app/tests/shared/appScale.test.ts +++ b/web/app/tests/shared/appScale.test.ts @@ -6,19 +6,17 @@ function readSource(path: string): string { } describe("default app scale", () => { - it("renders the full UI at 80 percent while preserving the scaled viewport height", () => { + it("renders the full UI at normal viewport scale", () => { const globals = readSource("src/shared/styles/globals.css"); const workspace = readSource("src/pages/WorkspacePage/components/WorkspaceComponents.css"); const workspaceLayout = readSource("src/pages/WorkspacePage/components/WorkspaceLayout/WorkspaceLayout.module.css"); const settings = readSource("src/pages/SettingsPage/SettingsPage.module.css"); - expect(globals).toContain("@supports (zoom: 80%)"); - expect(globals).toContain("--app-ui-viewport-height: 125dvh;"); - expect(globals).toContain("--text-xs-size: 13px;"); - expect(globals).toContain("--text-sm-size: 15px;"); - expect(globals).toContain("--text-md-size: 17px;"); - expect(globals).toContain("font-size-adjust: 0.65;"); - expect(globals).toContain("zoom: 80%;"); + expect(globals).toContain("--app-ui-viewport-height: 100dvh;"); + expect(globals).not.toContain("@supports (zoom: 80%)"); + expect(globals).not.toContain("--app-ui-viewport-height: 125dvh;"); + expect(globals).not.toContain("font-size-adjust: 0.65;"); + expect(globals).not.toContain("zoom: 80%;"); expect(globals).toContain("font-size: var(--text-md-size);"); expect(globals).toContain("font-family: var(--font-sans);"); expect(workspace).toContain("height: var(--app-ui-viewport-height);"); From f49c09ed6b6f8e03cba8de6db832432db7f81bb9 Mon Sep 17 00:00:00 2001 From: youngbeom Date: Mon, 13 Jul 2026 15:38:47 +0800 Subject: [PATCH 2/2] fix(web): update mcp sidebar icon --- .../ui/Icons/SidebarNavigationIcons.tsx | 26 +++++++++++++++++++ .../WorkspaceSidebar/WorkspaceSidebar.tsx | 5 ++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/web/app/src/components/ui/Icons/SidebarNavigationIcons.tsx b/web/app/src/components/ui/Icons/SidebarNavigationIcons.tsx index 3d372539..eb4d322b 100644 --- a/web/app/src/components/ui/Icons/SidebarNavigationIcons.tsx +++ b/web/app/src/components/ui/Icons/SidebarNavigationIcons.tsx @@ -166,6 +166,32 @@ export function SidebarPuzzlePiece02Icon({ size, ...props }: SidebarNavigationIc ); } +export function SidebarMcpIcon({ size, ...props }: SidebarNavigationIconProps) { + const resolvedSize = iconSize(size, 16); + return ( + + + + + + ); +} + export function SidebarBoxIcon({ size, ...props }: SidebarNavigationIconProps) { const resolvedSize = iconSize(size, 24); return ( diff --git a/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspaceSidebar.tsx b/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspaceSidebar.tsx index 392e79e5..d5bb89a1 100644 --- a/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspaceSidebar.tsx +++ b/web/app/src/pages/WorkspacePage/components/WorkspaceSidebar/WorkspaceSidebar.tsx @@ -1,11 +1,12 @@ import { useEffect, useMemo, useRef, useState } from "react"; -import { PanelLeftOpen, Plus, Search, Server } from "lucide-react"; +import { PanelLeftOpen, Plus, Search } from "lucide-react"; import { SidebarAlertTriangleIcon, SidebarBoxIcon, SidebarGrid07Icon, SidebarLaptopIcon, SidebarListUnordered4Icon, + SidebarMcpIcon, SidebarMessageIcon, SidebarPuzzlePiece02Icon, SidebarRobotIcon, @@ -304,7 +305,7 @@ export function WorkspaceSidebar({ active: activeContextSectionId === WorkspaceContextSectionIds.mcpServers, badge: badgeCount(hub?.mcpServers?.length), groupId: WorkspaceContextSectionIds.mcpServers, - icon: navigationIcon(Server), + icon: navigationIcon(SidebarMcpIcon), id: "mcp-servers", label: t("resourcesMCPLabel"), onSelect: () => {