fix(ui): sidebar dock margins, queue count footer, macOS NPB-small corner

Homologate the large-dock cover's side margins (16px each vs the visible content
bezel) and add a 4px bottom gap by trimming the FFT band 2px top/bottom. Move the
queue count out of the "Up Next" header into a fixed footer ("Showing X of Y
tracks", dropping the redundant "left"). On macOS, inset the flush-left NPB-small
art so the native rounded window corner stops clipping it.

cc
This commit is contained in:
vicrodh committed 2026-07-16 16:31:39 -06:00
1 parent f26d3e5e1d
commit 288e982b44
4 files changed
+38 -23

No files matched your search

+2 -2
View File
@@ -242,9 +242,9 @@ export component PlayerBar inherits Rectangle {
// row itself is NOT inset (PLAY stays window-centred), so only
// this card's content moves. New mode 0 keeps x:0/full width
// (identical to the previous fill default).
x: ShellState.large-active ? (ShellState.sidebar-rendered-width - 6px) : 0px;
x: ShellState.large-active ? (ShellState.sidebar-rendered-width + 8px) : 0px;
width: ShellState.large-active
? (parent.width - (ShellState.sidebar-rendered-width - 6px))
? (parent.width - (ShellState.sidebar-rendered-width + 8px))
: parent.width;
// Homologate the stamp with classic: full-size badge + LEDs,
// not the compact variant.
+6 -3
View File
@@ -47,7 +47,7 @@ import { SeekBar } from "SeekBar.slint";
import { SongCard } from "SongCard.slint";
import { TransportControls } from "TransportControls.slint";
import { AudioStamp } from "AudioStamp.slint";
import { NowPlayingState, ShellState, SettingsState, QconnectDevState, CastState, CastActions } from "../state.slint";
import { NowPlayingState, ShellState, SettingsState, QconnectDevState, CastState, CastActions, AppearanceState } from "../state.slint";
// Qobuz Connect button — monitor-speaker glyph; golden over a soft golden tint
// when a Qobuz Connect session owns playback. A local copy of PlayerBar's
@@ -210,8 +210,11 @@ export component PlayerBarSmall inherits Rectangle {
spacing: 0px;
// No left inset: the album art is FLUSH to the window's left
// edge; its 2px border provides the visual edge instead of a
// margin.
padding-left: 0px;
// margin. On macOS the native window's rounded bottom-left
// corner (~10pt since Big Sur) masks content at the very
// corner, so inset the flush-left art there to clear the
// curve; Linux no-frame corners are square (keep 0).
padding-left: AppearanceState.is-macos ? 8px : 0px;
// Art (37px, fits the ~39px controls row + leaves a hair of
// breathing room) + 2-line title/artist via SongCard. The art
+18 -6
View File
@@ -586,12 +586,9 @@ export component QueueSidebar inherits Rectangle {
// UP NEXT section.
if QueueState.upcoming-total > 0: VerticalLayout {
spacing: 8px;
// Counter — "UP NEXT (20 of 40, 38 left)".
// Section header — the count lives in the fixed footer.
Text {
text: @tr("UP NEXT ({} of {}, {} left)",
QueueState.page-end,
QueueState.upcoming-total,
QueueState.upcoming-remaining);
text: @tr("UP NEXT");
color: Theme.text-muted;
font-size: 11px;
font-weight: Typography.semibold;
@@ -763,11 +760,26 @@ export component QueueSidebar inherits Rectangle {
}
}
// --- Footer: four actions + inline search (Queue tab only) ------
// --- Footer: fixed count + four actions + inline search (Queue tab) ---
if QueueState.tab == 0 && !root.queue-empty: Rectangle {
height: 1px;
background: Theme.border-subtle;
}
// Fixed count — "Showing 40 of 109 tracks." Above the toolbar so it
// never scrolls with the list; total reflects the active queue search.
if QueueState.tab == 0 && !root.queue-empty && QueueState.upcoming-total > 0: HorizontalLayout {
padding-left: Spacing.md;
padding-right: Spacing.md;
padding-top: 8px;
alignment: center;
Text {
text: @tr("Showing {} of {} track." | "Showing {} of {} tracks." % QueueState.upcoming-total,
QueueState.page-end,
QueueState.upcoming-total);
color: Theme.text-muted;
font-size: 11px;
}
}
if QueueState.tab == 0 && !root.queue-empty: HorizontalLayout {
padding-left: Spacing.md;
padding-right: Spacing.md;
@@ -80,13 +80,14 @@ export component SidebarNowPlayingDock inherits Rectangle {
// Square cover = the dock's (sidebar content) width. Compact spectrum above.
property <length> art-size: root.width;
property <length> spectrum-h: 46px; // half the original 92px (owner: shorter band)
property <length> spectrum-h: 42px; // 46 - 4: trimmed 2px top + 2px bottom (owner: free space for the art's bottom gap)
// Reserve cover + (when ON) the spectrum band + gap, plus the top hairline
// pad. MUST equal ShellState.large-dock-height in BOTH toggle states so the
// AppShell overlay (y = root.height - large-dock-height) keeps the cover flush.
// pad and the 4px bottom gap. MUST equal ShellState.large-dock-height in BOTH
// toggle states so the AppShell overlay (y = root.height - large-dock-height)
// keeps the cover in place. ON = 9 + 42 + 10 + art + 4 = art+65; OFF = 9 + art + 4.
height: ShellState.large-visualizer-on
? (root.spectrum-h + 10px + root.art-size + 9px)
: (root.art-size + 9px);
? (root.spectrum-h + 10px + root.art-size + 13px)
: (root.art-size + 13px);
// Bars: 28 MIRRORED columns = 14 active source bins x2 (the 16-bin FFT
// excludes {1,15}; SpectrumPanel parity). More bars than the old straight 14.
@@ -110,13 +111,12 @@ export component SidebarNowPlayingDock inherits Rectangle {
VerticalLayout {
padding-top: 9px;
// Lift the cover 2px off the window bottom (it was flush) and take those
// 2px out of the cover<->spectrum gap (10 -> 8), so the dock height is
// unchanged (9 + spectrum + 8 + art + 2 == 9 + spectrum + 10 + art). The
// bottom pad applies only while the spectrum is shown — otherwise the
// off-state height would no longer match ShellState.large-dock-height.
spacing: 8px;
padding-bottom: ShellState.large-visualizer-on ? 2px : 0px;
// 4px gap below the cover vs the window bottom (both toggle states); the
// 4px was reclaimed by trimming the FFT band (46 -> 42). The FFT<->cover
// gap is the original 10px. Height stays in lockstep with
// ShellState.large-dock-height (state.slint) in both states.
spacing: 10px;
padding-bottom: 4px;
// ---- Spectrum band (only while the visualizer is ON) --------------
if ShellState.large-visualizer-on: spectrum := Rectangle {