From a09368fcd6017a46fdfabdbbdd131e66356b83b5 Mon Sep 17 00:00:00 2001 From: abundantbeing Date: Thu, 10 Sep 2026 22:14:35 +0700 Subject: [PATCH] fix(desktop): pin settings layout and HUD back to the right titlebar Keep panel tabs in the titlebar moved those app actions next to the sidebar toggle, which ate the tab strip. Put them back on the right edge. Sidebar toggle stays left. Fixes #107351. (cherry picked from commit 7f4460a7f6028cf384506733a5bfa52273792d64) --- apps/desktop/src/app/contrib/wiring.tsx | 15 ++++++---- .../src/app/shell/titlebar-controls.test.tsx | 20 ++++++++++++- .../src/app/shell/titlebar-controls.tsx | 28 +++++++++++++++++-- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/apps/desktop/src/app/contrib/wiring.tsx b/apps/desktop/src/app/contrib/wiring.tsx index 0a4a519886..9a043a1c51 100644 --- a/apps/desktop/src/app/contrib/wiring.tsx +++ b/apps/desktop/src/app/contrib/wiring.tsx @@ -1200,12 +1200,14 @@ export function ContribWiring({ children }: { children: ReactNode }) { } const titlebarToolsRight = titlebarToolsRightCss(nativeOverlayWidth, titlebarChrome) - // App controls live on the left; flip and the right toggle share the right. - const titlebarToolsWidth = titlebarToolsWidthCss(2) + // Right cluster: settings, layout, HUD, flip, right-sidebar toggle. + const SYSTEM_TOOL_COUNT = 5 + const paneToolCount = rightTitlebarTools.filter(tool => !tool.hidden).length + const systemToolsWidth = titlebarToolsWidthCss(SYSTEM_TOOL_COUNT) + const titlebarToolsWidth = + paneToolCount > 0 ? `calc(${systemToolsWidth} + ${titlebarToolsWidthCss(paneToolCount)})` : systemToolsWidth - const leftToolsWidth = titlebarToolsWidthCss( - 4 + [...leftTitlebarTools, ...rightTitlebarTools].filter(tool => !tool.hidden).length - ) + const leftToolsWidth = titlebarToolsWidthCss(1 + leftTitlebarTools.filter(tool => !tool.hidden).length) return ( @@ -1218,7 +1220,8 @@ export function ContribWiring({ children }: { children: ReactNode }) { '--titlebar-controls-width': leftToolsWidth, '--titlebar-controls-y-nudge': titlebarControlsYNudge(titlebarChrome), '--titlebar-tools-right': titlebarToolsRight, - '--titlebar-tools-width': titlebarToolsWidth + '--titlebar-tools-width': titlebarToolsWidth, + '--shell-preview-toolbar-gap': systemToolsWidth } as CSSProperties } > diff --git a/apps/desktop/src/app/shell/titlebar-controls.test.tsx b/apps/desktop/src/app/shell/titlebar-controls.test.tsx index 7f07695d73..df89595f31 100644 --- a/apps/desktop/src/app/shell/titlebar-controls.test.tsx +++ b/apps/desktop/src/app/shell/titlebar-controls.test.tsx @@ -1,5 +1,5 @@ // @vitest-environment jsdom -import { act, cleanup, render, screen } from '@testing-library/react' +import { act, cleanup, render, screen, within } from '@testing-library/react' import { MemoryRouter } from 'react-router' import { afterEach, beforeEach, describe, expect, it } from 'vitest' @@ -132,3 +132,21 @@ describe('TitlebarControls fixed clusters', () => { }) }) }) + +describe('titlebar app-action cluster', () => { + it('keeps settings, layout, and HUD on the right so the left titlebar stays free for tabs', () => { + renderControls('/') + + const left = screen.getByLabelText('Window controls') + const right = screen.getByLabelText('App controls') + + expect(within(right).getByLabelText('Open settings')).toBeTruthy() + expect(within(right).getByLabelText('Layout editor')).toBeTruthy() + expect(within(right).getByLabelText('HUD mode')).toBeTruthy() + + expect(within(left).queryByLabelText('Open settings')).toBeNull() + expect(within(left).queryByLabelText('Layout editor')).toBeNull() + expect(within(left).queryByLabelText('HUD mode')).toBeNull() + expect(within(left).getByLabelText(/Hide sidebar|Show sidebar/)).toBeTruthy() + }) +}) diff --git a/apps/desktop/src/app/shell/titlebar-controls.tsx b/apps/desktop/src/app/shell/titlebar-controls.tsx index df52dfd4b7..416ae7c674 100644 --- a/apps/desktop/src/app/shell/titlebar-controls.tsx +++ b/apps/desktop/src/app/shell/titlebar-controls.tsx @@ -196,7 +196,8 @@ export function TitlebarControls({ leftTools = [], tools = [], onOpenSettings }: tour: 'right-pane-toggle' } - // App actions stay visible beside the left sidebar toggle. + // Static system tools — always pinned to the screen's right edge so the + // left titlebar stays free for tabs (#107351). const systemTools: TitlebarTool[] = [ { actionId: 'nav.settings', @@ -285,7 +286,9 @@ export function TitlebarControls({ leftTools = [], tools = [], onOpenSettings }: ) } - const visibleLeftTools = [sidebarTool, ...systemTools, ...leftTools, ...tools].filter(tool => !tool.hidden) + const visibleLeftTools = [sidebarTool, ...leftTools].filter(tool => !tool.hidden) + const visibleSystemTools = systemTools.filter(tool => !tool.hidden) + const visiblePaneTools = tools.filter(tool => !tool.hidden) return ( <> @@ -293,16 +296,35 @@ export function TitlebarControls({ leftTools = [], tools = [], onOpenSettings }: {visibleLeftTools.map(tool => ( ))} - {titlebarSlots} + + + {visiblePaneTools.length > 0 && ( +
+ {visiblePaneTools.map(tool => ( + + ))} +
+ )} +
+ {visibleSystemTools.map(tool => ( + + ))} +
)