Files
qbz/crates/qbz-slint/ui/primitives/SidebarPlaylistCollage.slint
T
vicrodh 9f70a5ac5a feat(slint): sidebar Playlists toolbar + folders + micro-collage refinements
PLAYLISTS header: smaller title, recursive search (hides title), create
modal at 1:1 with Tauri (name/description/folder/public), sort menu, and a
collapse chevron. Folders: accent-tinted icon, open/close chevron as the
primary affordance (no more purposeless "..."), count shown on hover only.
Playlists render a 2x2 micro-collage of track covers (opt-out) instead of
the glyph, sourced from the existing playlist images (no extra fetch).

cc
2026-05-26 01:07:08 -06:00

70 lines
2.3 KiB
Plaintext

// Sidebar playlist micro-collage. A tiny (20px) thumbnail of a
// playlist's track covers shown in place of the generic list-music
// glyph, mirroring Tauri's PlaylistCoverCollage:
// - 0 covers -> parent renders the fallback glyph (nothing here)
// - 1-3 covers -> a single cover (the first tile), full bleed
// - 4+ covers -> a 2x2 grid, 1px gap, 3px radius
//
// The covers + decoded images live on the SidebarEntry (cover-count,
// cover1..cover4). This component only lays them out.
import { Theme } from "../foundation/semantic-colors.slint";
import { SidebarEntry } from "../state.slint";
export component SidebarPlaylistCollage inherits Rectangle {
in property <SidebarEntry> entry;
in property <length> size: 20px;
width: root.size;
height: root.size;
border-radius: 3px;
clip: true;
background: Theme.surface-elevated;
property <int> n: root.entry.cover-count;
property <length> gap: 1px;
// 1-3 covers -> single full-bleed cover (Tauri: tiles.length < 4).
if root.n >= 1 && root.n < 4: Image {
width: 100%;
height: 100%;
source: root.entry.cover1;
image-fit: cover;
}
// 4+ covers -> 2x2 grid (Tauri: tiles.slice(0, 4)).
if root.n >= 4: VerticalLayout {
spacing: root.gap;
HorizontalLayout {
spacing: root.gap;
Image {
source: root.entry.cover1;
image-fit: cover;
width: (root.size - root.gap) / 2;
height: (root.size - root.gap) / 2;
}
Image {
source: root.entry.cover2;
image-fit: cover;
width: (root.size - root.gap) / 2;
height: (root.size - root.gap) / 2;
}
}
HorizontalLayout {
spacing: root.gap;
Image {
source: root.entry.cover3;
image-fit: cover;
width: (root.size - root.gap) / 2;
height: (root.size - root.gap) / 2;
}
Image {
source: root.entry.cover4;
image-fit: cover;
width: (root.size - root.gap) / 2;
height: (root.size - root.gap) / 2;
}
}
}
}