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)
This commit is contained in:
abundantbeing
2026-09-10 22:14:35 +07:00
committed by brooklyn!
parent 75a6fac052
commit a09368fcd6
3 changed files with 53 additions and 10 deletions

View File

@@ -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 (
<ContribWiringContext.Provider value={api}>
@@ -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
}
>

View File

@@ -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()
})
})

View File

@@ -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 => (
<TitlebarToolButton key={tool.id} navigate={navigate} tool={tool} />
))}
{titlebarSlots}
<Slot area="titleBar.left" />
<Slot area="titleBar.center" />
</div>
{visiblePaneTools.length > 0 && (
<div
aria-label={t.shell.appControls}
className={cn(
titlebarToolClusterClass,
'top-[calc(var(--titlebar-controls-top)+var(--right-rail-top-inset,0px))] right-[calc(var(--titlebar-tools-right)+var(--shell-preview-toolbar-gap,0))]'
)}
>
{visiblePaneTools.map(tool => (
<TitlebarToolButton key={tool.id} navigate={navigate} tool={tool} />
))}
</div>
)}
<div
aria-label={t.shell.appControls}
className={cn(titlebarToolClusterClass, 'right-(--titlebar-tools-right) top-(--titlebar-controls-top)')}
data-titlebar-cluster="right"
>
{visibleSystemTools.map(tool => (
<TitlebarToolButton key={tool.id} navigate={navigate} tool={tool} />
))}
<TitlebarToolButton navigate={navigate} tool={flipTool} />
<TitlebarToolButton navigate={navigate} tool={rightSidebarTool} />
<Slot area="titleBar.right" />
</div>
</>
)