authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-08-14 11:22:05+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-14 11:22:05+02:00
log038560e58036d51b2576b3c2cd9170a194cefe9e
treea486f41aea786c653ffb746b7e50cb2040b13596
parent21a3669cee0c6fb54f5afe065cf0eb0348bd232c
signature Signed by PGP key B5690EEEBB952194

fix(web): align every titlebar control cluster on one shared inset (#6592)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

5 files changed, 31 insertions(+), 10 deletions(-)

apps/web/src/components/AppSidebarLayout.tsx+4-1
...@@ -96,8 +96,11 @@ function SidebarControl() {...@@ -96,8 +96,11 @@ function SidebarControl() {
96 }, [keybindings, toggleSidebar]);96 }, [keybindings, toggleSidebar]);
9797
98 return (98 return (
99 // The right-side layout controls carry mr-px (border compensation inside
100 // the panel), so the trigger mirrors it: both clusters sit one extra pixel
101 // off their edge and the titlebar reads symmetric.
99 <div102 <div
100 className="pointer-events-none fixed left-[var(--workspace-controls-left)] top-[var(--workspace-controls-top)] z-50 flex h-[var(--workspace-topbar-height)] items-center"103 className="pointer-events-none fixed left-[var(--workspace-controls-left)] top-[var(--workspace-controls-top)] z-50 ml-px flex h-[var(--workspace-topbar-height)] items-center"
101 data-sidebar-control=""104 data-sidebar-control=""
102 >105 >
103 <Tooltip>106 <Tooltip>
apps/web/src/components/ChatView.tsx+5-1
...@@ -6583,7 +6583,11 @@ function ChatViewContent(props: ChatViewProps) {...@@ -6583,7 +6583,11 @@ function ChatViewContent(props: ChatViewProps) {
6583 <RightPanelSheet open onClose={closePreviewPanel}>6583 <RightPanelSheet open onClose={closePreviewPanel}>
6584 <RightPanelTabs6584 <RightPanelTabs
6585 mode="sheet"6585 mode="sheet"
6586 layoutControls={panelToggleControls}6586 // Same effective inset as the closed-state titlebar controls
6587 // (pr-3 in the tab bar plus this pixel equals the absolute
6588 // right inset plus mr-px), so the cluster does not creep when
6589 // the sheet opens.
6590 layoutControls={<div className="mr-px flex items-center">{panelToggleControls}</div>}
6587 surfaces={rightPanelState.surfaces}6591 surfaces={rightPanelState.surfaces}
6588 activeSurfaceId={activeRightPanelSurface?.id ?? null}6592 activeSurfaceId={activeRightPanelSurface?.id ?? null}
6589 pendingSurfaceIds={pendingFileSurfaceIds}6593 pendingSurfaceIds={pendingFileSurfaceIds}
apps/web/src/components/RightPanelTabs.tsx+3-1
...@@ -604,7 +604,9 @@ export function RightPanelTabs(props: RightPanelTabsProps) {...@@ -604,7 +604,9 @@ export function RightPanelTabs(props: RightPanelTabsProps) {
604 <div604 <div
605 className={cn(605 className={cn(
606 "workspace-topbar gap-1 pl-2",606 "workspace-topbar gap-1 pl-2",
607 props.mode !== "inline" && "[--workspace-topbar-height:--spacing(11)]",607 // The sheet overlays from the viewport top, so its tab bar keeps
608 // the titlebar's height: a compact row re-centers the layout
609 // controls a few pixels higher and the cluster jumps on open.
608 props.mode === "inline" && !props.layoutControls ? "pr-28" : "pr-3",610 props.mode === "inline" && !props.layoutControls ? "pr-28" : "pr-3",
609 ownsDesktopTitleBar && "wco:pr-[calc(var(--workspace-native-controls-inset)+6rem)]",611 ownsDesktopTitleBar && "wco:pr-[calc(var(--workspace-native-controls-inset)+6rem)]",
610 props.mode === "inline" && props.maximized && COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS,612 props.mode === "inline" && props.maximized && COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS,
apps/web/src/components/chat/PanelLayoutControls.tsx+4-4
...@@ -48,7 +48,7 @@ export const PanelLayoutControls = memo(function PanelLayoutControls({...@@ -48,7 +48,7 @@ export const PanelLayoutControls = memo(function PanelLayoutControls({
48 size="sm"48 size="sm"
49 disabled={!terminalAvailable}49 disabled={!terminalAvailable}
50 >50 >
51 <PanelBottomIcon className="size-3.5" />51 <PanelBottomIcon className="size-4" />
52 </Toggle>52 </Toggle>
53 }53 }
54 />54 />
...@@ -75,7 +75,7 @@ export const PanelLayoutControls = memo(function PanelLayoutControls({...@@ -75,7 +75,7 @@ export const PanelLayoutControls = memo(function PanelLayoutControls({
75 size="sm"75 size="sm"
76 disabled={!rightPanelAvailable}76 disabled={!rightPanelAvailable}
77 >77 >
78 <PanelRightIcon className="size-3.5" />78 <PanelRightIcon className="size-4" />
79 {liveAgentCount > 0 ? (79 {liveAgentCount > 0 ? (
80 <span80 <span
81 aria-hidden81 aria-hidden
...@@ -122,9 +122,9 @@ export const RightPanelMaximizeControl = memo(function RightPanelMaximizeControl...@@ -122,9 +122,9 @@ export const RightPanelMaximizeControl = memo(function RightPanelMaximizeControl
122 size="sm"122 size="sm"
123 >123 >
124 {maximized ? (124 {maximized ? (
125 <Minimize2Icon className="size-3.5" />125 <Minimize2Icon className="size-4" />
126 ) : (126 ) : (
127 <Maximize2Icon className="size-3.5" />127 <Maximize2Icon className="size-4" />
128 )}128 )}
129 </Toggle>129 </Toggle>
130 }130 }
apps/web/src/routes/_chat.pull-requests.tsx+15-3
...@@ -1303,7 +1303,13 @@ function PullRequestsRouteView() {...@@ -1303,7 +1303,13 @@ function PullRequestsRouteView() {
1303 />1303 />
1304 );1304 );
1305 const openPanelControls = (1305 const openPanelControls = (
1306 <div className="workspace-titlebar-controls right-2 z-50 gap-1 [-webkit-app-region:no-drag] wco:right-[var(--workspace-controls-right)]">1306 <div
1307 // The bare workspace-titlebar-controls inset plus mr-px: the same
1308 // anchor the thread view's controls and the sidebar trigger use, so
1309 // every titlebar cluster in the app sits one shared inset from its
1310 // edge.
1311 className="workspace-titlebar-controls z-50 mr-px gap-1 [-webkit-app-region:no-drag]"
1312 >
1307 {panelToggleControls}1313 {panelToggleControls}
1308 </div>1314 </div>
1309 );1315 );
...@@ -1484,7 +1490,13 @@ function PullRequestsRouteView() {...@@ -1484,7 +1490,13 @@ function PullRequestsRouteView() {
1484 searchInput,1490 searchInput,
1485 filtersMenu,1491 filtersMenu,
1486 rightPanelControl:1492 rightPanelControl:
1487 !pullRequestsSupported || rightPanelState.isOpen ? null : panelToggleControls,1493 // Footprint reserve while the panel is closed: the toggle itself stays
1494 // mounted at the fixed titlebar inset in both states so it cannot move
1495 // on toggle, and this spacer keeps refresh from sliding underneath it
1496 // (sized per header padding so refresh ends a normal gap short of it).
1497 !pullRequestsSupported || rightPanelState.isOpen ? null : (
1498 <span aria-hidden className="w-7 shrink-0 sm:w-5" />
1499 ),
1488 rightPanelOpen: rightPanelState.isOpen,1500 rightPanelOpen: rightPanelState.isOpen,
1489 listBody,1501 listBody,
1490 };1502 };
...@@ -1526,7 +1538,7 @@ function PullRequestsRouteView() {...@@ -1526,7 +1538,7 @@ function PullRequestsRouteView() {
1526 return (1538 return (
1527 <SidebarInset className="h-dvh min-h-0 overflow-hidden overscroll-y-none bg-background text-foreground">1539 <SidebarInset className="h-dvh min-h-0 overflow-hidden overscroll-y-none bg-background text-foreground">
1528 <div className="relative flex min-h-0 flex-1">1540 <div className="relative flex min-h-0 flex-1">
1529 {pullRequestsSupported && rightPanelState.isOpen ? openPanelControls : null}1541 {pullRequestsSupported ? openPanelControls : null}
1530 <PullRequestsColumn {...columnProps} />1542 <PullRequestsColumn {...columnProps} />
15311543
1532 {rightPanelState.isOpen && activePullRequestSurface && panelEnvironmentId !== null ? (1544 {rightPanelState.isOpen && activePullRequestSurface && panelEnvironmentId !== null ? (