feat(qbz-slint): RadioCard 200px + hover-reveal scrollbar base
- RadioCard enlarged to 200x246 to match Album/Playlist cards; ForYouView + Spotlight row-width math updated to 200. - Scrollbar hover-reveal: ListScrollbar gains a reveal prop (default true, no regression) and fades on opacity; TrackRow exposes hover-changed; AlbumPageView wired as the verified template (row-hover count -> reveal). cc
This commit is contained in:
6 files changed
+41
-12
No files matched your search
@@ -117,6 +117,10 @@ export component AlbumPageView inherits Rectangle {
|
||||
callback open-artist(string);
|
||||
callback media-action(string, string, string);
|
||||
|
||||
// Count of track rows currently hovered (>0 = pointer over the list) — the
|
||||
// hover-reveal source for the scrollbar (sidebar pattern).
|
||||
property <int> scroll-hover-rows: 0;
|
||||
|
||||
// Whether the full-description modal is open.
|
||||
property <bool> show-description: false;
|
||||
|
||||
@@ -599,6 +603,11 @@ export component AlbumPageView inherits Rectangle {
|
||||
media-action(kind, id, action) => {
|
||||
root.media-action(kind, id, action);
|
||||
}
|
||||
hover-changed(h) => {
|
||||
root.scroll-hover-rows = h
|
||||
? root.scroll-hover-rows + 1
|
||||
: Math.max(0, root.scroll-hover-rows - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,7 +646,8 @@ export component AlbumPageView inherits Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
// Shared scrollbar in the right gutter (homologated cross-view).
|
||||
// Shared scrollbar in the right gutter (homologated cross-view). Hover-
|
||||
// reveal: shown while the pointer is over the track rows (or the gutter).
|
||||
ListScrollbar {
|
||||
x: parent.width - self.width - 4px;
|
||||
width: 14px;
|
||||
@@ -645,6 +655,7 @@ export component AlbumPageView inherits Rectangle {
|
||||
viewport-height: flick.viewport-height;
|
||||
visible-height: flick.height;
|
||||
viewport-y <=> flick.viewport-y;
|
||||
reveal: root.scroll-hover-rows > 0;
|
||||
}
|
||||
|
||||
// --- Full-description modal --------------------------------------------
|
||||
|
||||
@@ -74,7 +74,7 @@ export component ForYouView inherits VerticalLayout {
|
||||
radio-flick := Flickable {
|
||||
width: 100%;
|
||||
height: parent.height;
|
||||
viewport-width: ForYouState.radio-stations.length * (180px + 32px);
|
||||
viewport-width: ForYouState.radio-stations.length * (200px + 32px);
|
||||
viewport-height: self.height;
|
||||
HorizontalLayout {
|
||||
spacing: 32px;
|
||||
|
||||
@@ -20,24 +20,25 @@ export component RadioCard inherits Rectangle {
|
||||
callback clicked();
|
||||
callback play();
|
||||
|
||||
width: 180px;
|
||||
height: 234px;
|
||||
// Matches AlbumCard / PlaylistCard (200 x 246): panel 200 + 8 + meta.
|
||||
width: 200px;
|
||||
height: 246px;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 8px;
|
||||
|
||||
// Display panel.
|
||||
panel := Rectangle {
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: Radius.sm;
|
||||
background: Theme.surface-elevated;
|
||||
clip: true;
|
||||
|
||||
// Centered artwork "display".
|
||||
Rectangle {
|
||||
width: 114px;
|
||||
height: 114px;
|
||||
width: 126px;
|
||||
height: 126px;
|
||||
x: (parent.width - self.width) / 2;
|
||||
y: (parent.height - self.height) / 2 - 8px;
|
||||
border-radius: 4px;
|
||||
@@ -110,14 +111,14 @@ export component RadioCard inherits Rectangle {
|
||||
font-size: Typography.body;
|
||||
font-weight: Typography.medium;
|
||||
overflow: elide;
|
||||
width: 180px;
|
||||
width: 200px;
|
||||
}
|
||||
if root.seed-subtitle != "": Text {
|
||||
text: root.seed-subtitle;
|
||||
color: Theme.text-muted;
|
||||
font-size: Typography.legal;
|
||||
overflow: elide;
|
||||
width: 180px;
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,10 +45,10 @@ export component Spotlight inherits VerticalLayout {
|
||||
callback media-action(string, string, string);
|
||||
|
||||
property <length> gap: 24px;
|
||||
// Row content width: TopTracks(180) + Radio(180) + albums(220 each)
|
||||
// Row content width: TopTracks(200) + Radio(200) + albums(200 each)
|
||||
// + gaps. has-top-tracks toggles the first card.
|
||||
property <length> radio-cards-width:
|
||||
(ForYouState.spotlight-has-top-tracks ? 180px + root.gap : 0px) + 180px + root.gap;
|
||||
(ForYouState.spotlight-has-top-tracks ? 200px + root.gap : 0px) + 200px + root.gap;
|
||||
property <int> album-count: ForYouState.spotlight-albums.length;
|
||||
property <length> content-width:
|
||||
root.radio-cards-width
|
||||
|
||||
@@ -11,9 +11,18 @@ export component ListScrollbar inherits Rectangle {
|
||||
in property <length> viewport-height;
|
||||
in property <length> visible-height;
|
||||
in-out property <length> viewport-y;
|
||||
// Hover-reveal: the owning view sets this true while the pointer is over the
|
||||
// scrollable rows; the bar also reveals on its own gutter hover/drag. When
|
||||
// false it fades out. DEFAULTS TRUE so views that don't wire it keep the bar
|
||||
// always visible (no behaviour change until a view opts in).
|
||||
in property <bool> reveal: true;
|
||||
|
||||
// Only meaningful when the content overflows.
|
||||
property <length> max-scroll: max(0px, root.viewport-height - root.visible-height);
|
||||
|
||||
// Fade out unless revealed (by row hover) or the gutter itself is engaged.
|
||||
opacity: (root.reveal || bar-ta.has-hover || bar-ta.pressed) ? 1.0 : 0.0;
|
||||
animate opacity { duration: 150ms; }
|
||||
property <length> thumb-h:
|
||||
root.viewport-height > 0px
|
||||
? max(48px, root.visible-height / root.viewport-height * root.height)
|
||||
|
||||
@@ -47,12 +47,20 @@ export component TrackRow inherits Rectangle {
|
||||
// Whether the row can be dragged onto sidebar playlists.
|
||||
in property <bool> draggable: true;
|
||||
callback media-action(string, string, string);
|
||||
// Reports the row's overall hover state so a list view can reveal its
|
||||
// scrollbar while the pointer is anywhere over the rows (the proven sidebar
|
||||
// pattern — a background/Flickable-level TouchArea can't see hover over a
|
||||
// row's own touch areas).
|
||||
callback hover-changed(bool);
|
||||
|
||||
// Explicit track number, else the 1-based list position.
|
||||
property <string> number-text:
|
||||
root.track.number != "" ? root.track.number : "\{root.index + 1}";
|
||||
property <bool> row-hovered:
|
||||
ta.has-hover || play-cell.hovered || more-ta.has-hover;
|
||||
changed row-hovered => {
|
||||
root.hover-changed(self.row-hovered);
|
||||
}
|
||||
|
||||
height: 50px;
|
||||
border-radius: 8px;
|
||||
|
||||
Reference in new issue
Block a user