fix(qt): the player bar is one chrome band like the header, with its layout inset

The bottom band is now NowPlayingBar.qml's root: full width, flush on the
window's bottom edge, surface-card @ 0.5 over the ambient field like the
HeaderBar, opaque surface-card otherwise. The bar layout (PlayerBar /
NowPlayingBarSmall) paints no background of its own and mounts inset by the
gutter on its left, right and bottom, so the bar's ends still line up with
the content pane's while nothing around it shows the raw field. Both
rejected shapes are documented in place: an inset plate over the raw field
(three sides of raw background, the only zone of the shell without chrome)
and a frame slab behind an inset plate (a bar glued onto a slab). A future
layout inherits the band and the gutter from the seam instead of carrying
either.

cc
This commit is contained in:
vicrodh committed 2026-09-13 15:38:25 -06:00
1 parent cadbb768fc
commit d05082eaee
4 files changed
+54 -29

No files matched your search

+11 -20
View File
@@ -252,12 +252,14 @@ Rectangle {
hostName: QbzOrbit.hostName hostName: QbzOrbit.hostName
} }
// The gutter the player bar keeps to the window edges (below). Nothing // The bottom chrome band (NowPlayingBar.qml's root): full width, flush
// is painted behind it: the bar floats over the shell's own ground — // on the window's bottom edge, the same tier and paint as the HeaderBar
// the ambient field or the root colour — exactly like the content pane's // above. The bar layout inside it keeps the content pane's gutter to the
// margins show what is under them (a backdrop was tried and rejected). // window's left, right and bottom edges — wider on macOS, where the
readonly property int npbGutter: Qt.platform.os === "osx" ? theme.npbGutterMac : theme.npbGutter // Liquid Glass corner curve ate the cover's corner (QbzTheme.npbGutterMac)
// — and the band sizes itself: the mode-aware layout height (Small
// collapses to one header-tall row; New/Classic/Large keep the full
// 112px, AppShell.slint:396) plus that gutter.
NowPlayingBar { NowPlayingBar {
id: npb id: npb
// The small seek thumb/hit area extends above the bar by a few pixels. // The small seek thumb/hit area extends above the bar by a few pixels.
@@ -267,17 +269,6 @@ Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom 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
// The shared hover-tooltip overlay (declared further down — id // The shared hover-tooltip overlay (declared further down — id
// references resolve at completion). All four modes consume it for // references resolve at completion). All four modes consume it for
// Shuffle/Repeat state; the full bar also uses it for Qobuz Connect. // Shuffle/Repeat state; the full bar also uses it for Qobuz Connect.
@@ -666,9 +657,9 @@ Rectangle {
// so this width also sets the art size. // so this width also sets the art size.
x: 16 x: 16
width: 208 width: 208
// Flush with the bar's bottom edge, which now sits a gutter above // Flush with the bar LAYOUT's bottom edge, which sits a gutter above
// the window's (npbGutter) — the dock lifts with it. // the window's (the band's inset) — the dock lifts with it.
y: npb.y + npb.height - QbzShell.largeDockHeight y: npb.y + npb.height - npb.gutter - QbzShell.largeDockHeight
ambientOn: root.ambientOn ambientOn: root.ambientOn
} }
+33 -3
View File
@@ -1,13 +1,39 @@
// NowPlayingBar SHELL — the mode seam (NowPlayingBar.slint, phase 18): // NowPlayingBar SHELL — the mode seam (NowPlayingBar.slint, phase 18):
// mounts NowPlayingBarSmall for mode 2 (Small) and the full PlayerBar for // mounts NowPlayingBarSmall for mode 2 (Small) and the full PlayerBar for
// modes 0 (New) / 1 (Classic) / 3 (Large). AppShell pins the height // modes 0 (New) / 1 (Classic) / 3 (Large), and sizes itself mode-aware
// mode-aware (42px Small / 112px otherwise). // (42px Small / 112px otherwise, plus the gutter below).
//
// THE BAND (2026-09-13). This root is the bottom chrome band, the exact
// counterpart of HeaderBar at the top: one full-width piece of chrome, flush
// on the window's bottom edge, painted surface-card @ 0.5 over the field
// while the ambient background is active and opaque surface-card otherwise.
// The bar LAYOUT mounted below is inset by `gutter` on its left, right and
// bottom, so the bar's ends line up with the content pane's and nothing in
// it touches the window edge — while the band stays continuous around it.
// Both alternatives were tried and rejected the same day: insetting the
// whole bar left the raw field showing on three sides (the only zone of the
// shell without chrome), and a frame slab behind an inset plate read as a
// bar glued onto a slab. A layout knows nothing about the band or the
// gutter: it paints no background of its own and fills the rect it is given,
// which is what keeps a future layout from needing either.
import QtQuick import QtQuick
import com.blitzfc.qbz import com.blitzfc.qbz
import "../theme"
Item { Rectangle {
id: root id: root
color: ambientOn ? theme.surfaceCardA50 : theme.surfaceCard
readonly property bool ambientOn: theme.ambientOn
QbzTheme { id: theme }
/// The gutter the bar layout keeps to the window's left, right and
/// bottom edges: the pane's 8px, wider on macOS (QbzTheme.npbGutterMac).
readonly property int gutter: Qt.platform.os === "osx" ? theme.npbGutterMac : theme.npbGutter
/// The layout's own height (PlayerBar.slint / PlayerBarSmall.slint).
readonly property int layoutHeight: QbzShell.npbMode === 2 ? theme.npbSmallHeight : theme.npbLargeHeight
implicitHeight: layoutHeight + gutter
// The shell's shared hover-tooltip overlay (controls/QbzTooltip.qml), // The shell's shared hover-tooltip overlay (controls/QbzTooltip.qml),
// fed in by AppShell (same pattern as Sidebar.tooltip). Forwarded into // fed in by AppShell (same pattern as Sidebar.tooltip). Forwarded into
@@ -18,6 +44,10 @@ Item {
Loader { Loader {
id: barLoader id: barLoader
anchors.fill: parent anchors.fill: parent
// The inset. Top stays flush: the band's top edge IS the layout's.
anchors.leftMargin: root.gutter
anchors.rightMargin: root.gutter
anchors.bottomMargin: root.gutter
source: QbzShell.npbMode === 2 ? "NowPlayingBarSmall.qml" : "PlayerBar.qml" source: QbzShell.npbMode === 2 ? "NowPlayingBarSmall.qml" : "PlayerBar.qml"
} }
@@ -40,9 +40,10 @@ import "../theme"
Rectangle { Rectangle {
id: root id: root
// surface-card @ 0.5 while the ambient background is active (phase 14, // No background of its own: the chrome band is NowPlayingBar.qml's root
// PlayerBarSmall.slint). // (surface-card @ 0.5 under the ambient background, opaque surface-card
color: ambientOn ? theme.surfaceCardA50 : theme.surfaceCard // otherwise), full width behind this inset layout — see THE BAND there.
color: "transparent"
readonly property bool ambientOn: theme.ambientOn readonly property bool ambientOn: theme.ambientOn
/// AppShell's one shared hover-tooltip overlay. /// AppShell's one shared hover-tooltip overlay.
property Item tooltip: null property Item tooltip: null
@@ -65,7 +66,7 @@ Rectangle {
// 1366 / 1920) are the SHARED theme token, so this bar and PlayerBar can // 1366 / 1920) are the SHARED theme token, so this bar and PlayerBar can
// never drift apart — see QbzTheme.npbSideFrac. // never drift apart — see QbzTheme.npbSideFrac.
// `root.width` is the window width minus the two side gutters // `root.width` is the window width minus the two side gutters
// (AppShell `npbGutter`): the bar is anchored left-to-right on the shell // (NowPlayingBar.qml `gutter`): the bar is anchored left-to-right on the shell
// root, exactly like PlayerBarSmall.slint reads its own root. // root, exactly like PlayerBarSmall.slint reads its own root.
property real sideFrac: theme.npbSideFrac(root.width) property real sideFrac: theme.npbSideFrac(root.width)
property real colCentre: 1.0 - 2.0 * root.sideFrac property real colCentre: 1.0 - 2.0 * root.sideFrac
+5 -2
View File
@@ -69,7 +69,10 @@ import "../theme"
Rectangle { Rectangle {
id: root id: root
color: ambientOn ? theme.surfaceCardA50 : theme.surfaceCard // No background of its own: the chrome band is NowPlayingBar.qml's root
// (surface-card @ 0.5 under the ambient background, opaque surface-card
// otherwise), full width behind this inset layout — see THE BAND there.
color: "transparent"
readonly property bool ambientOn: theme.ambientOn readonly property bool ambientOn: theme.ambientOn
readonly property bool largeActive: QbzShell.npbMode === 3 && QbzShell.sidebarState === 0 readonly property bool largeActive: QbzShell.npbMode === 3 && QbzShell.sidebarState === 0
readonly property bool isClassic: QbzShell.npbMode === 1 readonly property bool isClassic: QbzShell.npbMode === 1
@@ -103,7 +106,7 @@ Rectangle {
// are the SHARED theme token (QbzTheme.npbSideFrac) — the Small bar reads // are the SHARED theme token (QbzTheme.npbSideFrac) — the Small bar reads
// the same one, so the two bars cannot drift apart. // the same one, so the two bars cannot drift apart.
// `root.width` is the window width minus the two side gutters // `root.width` is the window width minus the two side gutters
// (AppShell `npbGutter`): the bar is anchored left-to-right on the shell // (NowPlayingBar.qml `gutter`): the bar is anchored left-to-right on the shell
// root, exactly like PlayerBar.slint reads its own root. // root, exactly like PlayerBar.slint reads its own root.
property real sideFrac: theme.npbSideFrac(root.width) property real sideFrac: theme.npbSideFrac(root.width)
property real colSide: isClassic ? 0.324 : sideFrac property real colSide: isClassic ? 0.324 : sideFrac