diff --git a/crates/qbz-qt/qml/shell/AppShell.qml b/crates/qbz-qt/qml/shell/AppShell.qml index b5e204351..09b6a3ced 100644 --- a/crates/qbz-qt/qml/shell/AppShell.qml +++ b/crates/qbz-qt/qml/shell/AppShell.qml @@ -252,6 +252,21 @@ Rectangle { hostName: QbzOrbit.hostName } + // The player bar's FRAME — the same chrome tier as the sidebar and the + // content frame, so the gutter around the inset bar reads as one + // continuous frame and never as a band of raw background (the same rule + // the content frame documents below). It spans the bar's height plus + // the bottom gutter, full width, so the side gutters are covered too. + readonly property int npbGutter: Qt.platform.os === "osx" ? theme.npbGutterMac : theme.npbGutter + Rectangle { + id: npbFrame + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + height: npb.height + root.npbGutter + color: root.ambientOn ? theme.surfaceCardA50 : theme.surfaceCard + } + NowPlayingBar { id: npb // The small seek thumb/hit area extends above the bar by a few pixels. @@ -261,6 +276,14 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom + // Inset by the content pane's gutter on the three window edges + // (2026-09-13, every mode): the bar's ends line up with the pane's + // and nothing in it touches the window edge — wider on macOS, where + // the Liquid Glass corner curve ate the cover's corner + // (QbzTheme.npbGutterMac). + anchors.leftMargin: root.npbGutter + anchors.rightMargin: root.npbGutter + anchors.bottomMargin: root.npbGutter // Mode-aware height (AppShell.slint:396): Small collapses to one // header-tall row; New/Classic/Large keep the full 112px. height: QbzShell.npbMode === 2 ? theme.npbSmallHeight : theme.npbLargeHeight @@ -652,7 +675,9 @@ Rectangle { // so this width also sets the art size. x: 16 width: 208 - y: parent.height - QbzShell.largeDockHeight + // Flush with the bar's bottom edge, which now sits a gutter above + // the window's (npbGutter) — the dock lifts with it. + y: npb.y + npb.height - QbzShell.largeDockHeight ambientOn: root.ambientOn } diff --git a/crates/qbz-qt/qml/shell/NowPlayingBarSmall.qml b/crates/qbz-qt/qml/shell/NowPlayingBarSmall.qml index 5ac6f5f70..5f0f64f50 100644 --- a/crates/qbz-qt/qml/shell/NowPlayingBarSmall.qml +++ b/crates/qbz-qt/qml/shell/NowPlayingBarSmall.qml @@ -64,8 +64,9 @@ Rectangle { // column lands PLAY on the window centre. The breakpoints (39/30/25 at // 1366 / 1920) are the SHARED theme token, so this bar and PlayerBar can // never drift apart — see QbzTheme.npbSideFrac. - // `root.width` IS the window width: the bar is anchored left-to-right on - // the shell root, exactly like PlayerBarSmall.slint reads its own root. + // `root.width` is the window width minus the two side gutters + // (AppShell `npbGutter`): the bar is anchored left-to-right on the shell + // root, exactly like PlayerBarSmall.slint reads its own root. property real sideFrac: theme.npbSideFrac(root.width) property real colCentre: 1.0 - 2.0 * root.sideFrac // WIDE = inline horizontal volume slider; NARROW = button-only. diff --git a/crates/qbz-qt/qml/shell/PlayerBar.qml b/crates/qbz-qt/qml/shell/PlayerBar.qml index 6e2113116..6a1618c37 100644 --- a/crates/qbz-qt/qml/shell/PlayerBar.qml +++ b/crates/qbz-qt/qml/shell/PlayerBar.qml @@ -102,8 +102,9 @@ Rectangle { // columns EQUAL so the centre column stays dead centre. The breakpoints // are the SHARED theme token (QbzTheme.npbSideFrac) — the Small bar reads // the same one, so the two bars cannot drift apart. - // `root.width` IS the window width: the bar is anchored left-to-right on - // the shell root, exactly like PlayerBar.slint reads its own root. + // `root.width` is the window width minus the two side gutters + // (AppShell `npbGutter`): the bar is anchored left-to-right on the shell + // root, exactly like PlayerBar.slint reads its own root. property real sideFrac: theme.npbSideFrac(root.width) property real colSide: isClassic ? 0.324 : sideFrac property real colCentre: 1.0 - 2.0 * colSide diff --git a/crates/qbz-qt/qml/theme/QbzTheme.qml b/crates/qbz-qt/qml/theme/QbzTheme.qml index cd3746448..f6fb537d1 100644 --- a/crates/qbz-qt/qml/theme/QbzTheme.qml +++ b/crates/qbz-qt/qml/theme/QbzTheme.qml @@ -419,6 +419,19 @@ QtObject { // Small now-playing bar total height (ShellState.npb-small-height, // npb-small-extra is 0 on Linux). readonly property int npbSmallHeight: 42 + /// The gutter the player bar keeps to the window's left, right and + /// bottom edges (2026-09-13): the SAME 8 px the content pane keeps + /// inside its frame, so the bar's ends line up with the pane's and + /// nothing in it touches the window edge. + readonly property int npbGutter: 8 + /// macOS only: Tahoe's Liquid Glass windows round their corners far + /// more than before (Apple: toolbar windows take a larger radius that + /// "can clip content that sits close to the edge of the window"; + /// estimates run from ~12-16 pt for titlebar-only windows to 50 px+ + /// with a toolbar) and the cover at the bar's left end lost its corner. + /// Qt has no LayoutRegion to nest content into the curve, so the bar + /// simply keeps a wider gutter there. + readonly property int npbGutterMac: 16 // Every other bar mode (New / Classic / Large) — AppShell.slint:396. // The Large dock's sidebar reservation subtracts this, so it must be the // SAME value the shell pins the bar to.