feat(slint): library/sidebar UX overhaul + theme switching + fixes

Shell & navigation:
- Three-state sidebar (open/mini/closed); collapse cycles via header button.
- Section nav as right-flyouts (sidebar) + compact header nav (closed) +
  full header tabs (nav-in-sidebar off), via a shared HeaderMenuOverlay.
- Collapsed-folder right-flyout popup (max 4 + scrollbar), Rust-populated.
- Thin auto-hiding sidebar scrollbar pinned to the edge (Flickable, drag-safe).
- Slack-style bezel: rounded inset content panel over surface-card chrome.
- Header restructure: nav buttons, window-centered search, app menu.

Themes & components:
- Live theme switching: Dark / OLED Black / Tokyo Night / System (std-widgets).
- SegmentedTabBar (Discovery-style) with count badges for Library + Local Library.
- MP3 quality-badge tier (format-first classification) across badges.
- QbzSelect (Group/Sort) trimmed 20px.

Behavior fixes:
- Artist + Local Library Folder cover art now reach the rendered (visible/
  grouped) models, not just the source set.
- Favorites Playlists/Labels random buttons.
- Playlist track click plays from the clicked track in visible order.
- Dropdown idle-close pauses while the cursor rests on the menu.

cc
This commit is contained in:
vicrodh committed 2026-05-30 15:40:35 -06:00
1 parent 201082d4a1
commit 682719cab0
27 files changed
+1495 -619

No files matched your search

+22 -3
View File
@@ -16,7 +16,7 @@ import { Radius } from "../foundation/radius.slint";
import { QbzIcon } from "../primitives/QbzIcon.slint";
import { QbzSlider } from "../primitives/QbzSlider.slint";
import { SeekBar } from "SeekBar.slint";
import { NowPlayingState } from "../state.slint";
import { NowPlayingState, ShellState, AppearanceState } from "../state.slint";
component IconButton inherits Rectangle {
in property <image> icon;
@@ -257,6 +257,24 @@ export component PlayerBar inherits Rectangle {
IconButton { icon: @image-url("../assets/icons/maximize-2.svg"); icon-size: 16px; }
IconButton { icon: @image-url("../assets/icons/audio-lines.svg"); icon-size: 16px; }
// Lyrics + queue panel toggles (moved here from the header).
IconButton {
icon: @image-url("../assets/icons/captions.svg");
icon-size: 16px;
active: ShellState.right-panel == 2;
clicked => {
ShellState.right-panel = ShellState.right-panel == 2 ? 0 : 2;
}
}
IconButton {
icon: @image-url("../assets/icons/list-ordered.svg");
icon-size: 16px;
active: ShellState.right-panel == 1;
clicked => {
ShellState.right-panel = ShellState.right-panel == 1 ? 0 : 1;
}
}
Rectangle { width: 6px; }
IconButton {
@@ -281,14 +299,15 @@ export component PlayerBar inherits Rectangle {
}
}
}
IconButton {
// Volume +/- steppers — opt-in (Settings > Appearance).
if AppearanceState.show-volume-steppers: IconButton {
icon: @image-url("../assets/icons/minus.svg");
icon-size: 15px;
clicked => {
NowPlayingState.set-volume(Math.max(0.0, NowPlayingState.volume - 0.05));
}
}
IconButton {
if AppearanceState.show-volume-steppers: IconButton {
icon: @image-url("../assets/icons/plus.svg");
icon-size: 15px;
clicked => {