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
}
// The gutter the player bar keeps to the window edges (below). Nothing
// is painted behind it: the bar floats over the shell's own ground —
// the ambient field or the root colour — exactly like the content pane's
// margins show what is under them (a backdrop was tried and rejected).
readonly property int npbGutter: Qt.platform.os === "osx" ? theme.npbGutterMac : theme.npbGutter
// The bottom chrome band (NowPlayingBar.qml's root): full width, flush
// on the window's bottom edge, the same tier and paint as the HeaderBar
// above. The bar layout inside it keeps the content pane's gutter to the
// window's left, right and bottom edges — wider on macOS, where the
// 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 {
id: npb
// The small seek thumb/hit area extends above the bar by a few pixels.
@@ -267,17 +269,6 @@ 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
// The shared hover-tooltip overlay (declared further down — id
// references resolve at completion). All four modes consume it for
// 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.
x: 16
width: 208
// 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
// Flush with the bar LAYOUT's bottom edge, which sits a gutter above
// the window's (the band's inset) — the dock lifts with it.
y: npb.y + npb.height - npb.gutter - QbzShell.largeDockHeight
ambientOn: root.ambientOn
}
+33 -3
View File
@@ -1,13 +1,39 @@
// NowPlayingBar SHELL — the mode seam (NowPlayingBar.slint, phase 18):
// mounts NowPlayingBarSmall for mode 2 (Small) and the full PlayerBar for
// modes 0 (New) / 1 (Classic) / 3 (Large). AppShell pins the height
// mode-aware (42px Small / 112px otherwise).
// modes 0 (New) / 1 (Classic) / 3 (Large), and sizes itself mode-aware
// (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 com.blitzfc.qbz
import "../theme"
Item {
Rectangle {
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),
// fed in by AppShell (same pattern as Sidebar.tooltip). Forwarded into
@@ -18,6 +44,10 @@ Item {
Loader {
id: barLoader
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"
}
@@ -40,9 +40,10 @@ import "../theme"
Rectangle {
id: root
// surface-card @ 0.5 while the ambient background is active (phase 14,
// PlayerBarSmall.slint).
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
/// AppShell's one shared hover-tooltip overlay.
property Item tooltip: null
@@ -65,7 +66,7 @@ Rectangle {
// 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 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.
property real sideFrac: theme.npbSideFrac(root.width)
property real colCentre: 1.0 - 2.0 * root.sideFrac
+5 -2
View File
@@ -69,7 +69,10 @@ import "../theme"
Rectangle {
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 largeActive: QbzShell.npbMode === 3 && QbzShell.sidebarState === 0
readonly property bool isClassic: QbzShell.npbMode === 1
@@ -103,7 +106,7 @@ Rectangle {
// 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 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.
property real sideFrac: theme.npbSideFrac(root.width)
property real colSide: isClassic ? 0.324 : sideFrac