Files
qbz/crates/qbz-slint/ui/primitives/SegmentedTabBar.slint
T
vicrodh 682719cab0 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
2026-05-30 15:40:35 -06:00

96 lines
3.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Segmented tab navigator — the SAME design Discovery's HomeView uses (a
// small-radius rectangle group, ADR-008-compliant: NOT a capsule pill),
// promoted to a shared, data-driven primitive so Local Library and Library
// (Favorites) read identically. Each tab carries an optional count rendered
// as a compact badge with smaller-but-legible type inside the tab item.
import { Theme } from "../foundation/semantic-colors.slint";
import { Typography } from "../foundation/typography.slint";
// One entry in the navigator. `count <= 0` hides the badge.
export struct SegTab {
id: string,
label: string,
count: int,
}
// A single segment: fills with surface-main when active (Discovery's Tab),
// hover surface-hover, transparent otherwise. The count sits in a rounded
// badge to the right of the label.
component Segment inherits Rectangle {
in property <string> label;
in property <int> count;
in property <bool> active;
callback clicked();
border-radius: 4px;
background: root.active ? Theme.surface-main
: ta.has-hover ? Theme.surface-hover : transparent;
HorizontalLayout {
padding-left: 12px;
padding-right: root.count > 0 ? 8px : 12px;
padding-top: 6px;
padding-bottom: 6px;
spacing: 7px;
Text {
text: root.label;
color: root.active ? Theme.text-primary : Theme.text-muted;
// Discovery's tab type: 13px medium.
font-size: Typography.legal;
font-weight: Typography.medium;
vertical-alignment: center;
}
// Count badge — smaller (11px) but legible. min-width keeps single
// digits balanced; the layout grows the chip for 2–3 digit counts.
if root.count > 0: VerticalLayout {
alignment: center;
Rectangle {
min-width: 18px;
height: 16px;
border-radius: 8px;
background: root.active ? #ffffff24 : #ffffff14;
HorizontalLayout {
alignment: center;
padding-left: 5px;
padding-right: 5px;
Text {
text: root.count;
color: root.active ? Theme.text-primary : Theme.text-secondary;
font-size: 11px;
font-weight: Typography.medium;
vertical-alignment: center;
}
}
}
}
}
ta := TouchArea {
mouse-cursor: pointer;
clicked => { root.clicked(); }
}
}
export component SegmentedTabBar inherits Rectangle {
in property <[SegTab]> tabs;
in property <string> active-id;
callback selected(string);
width: row.preferred-width;
height: row.preferred-height;
background: Theme.surface-elevated;
border-radius: 6px;
row := HorizontalLayout {
padding: 3px;
spacing: 4px;
for tab in root.tabs: Segment {
label: tab.label;
count: tab.count;
active: root.active-id == tab.id;
clicked => { root.selected(tab.id); }
}
}
}