style(slint): sm toolbar variant + center bulk-bar actions

Add a Bootstrap-style `sm` flag to the shared toolbar primitives
(QbzSelect, ExpandableSearch, ToggleButton) — default stays the standard
size (Settings keeps it), and the favorites toolbar opts in (genre /
group / sort / search / grid-list now ~30px). FavGenreButton + the
favorites grid/list ViewToggle shrink to match. Also vertically center
the MultiSelectBar action buttons (only the count was centered before).

cc
This commit is contained in:
vicrodh committed 2026-05-27 11:16:38 -06:00
1 parent dbd6d2e4b5
commit 159310bbf0
5 files changed
+49 -32

No files matched your search

@@ -303,22 +303,22 @@ component FavArtistCard inherits Rectangle {
component FavGenreButton inherits Rectangle {
property <bool> active: GenreFilterState.selected-count > 0;
width: genre-row.preferred-width;
height: 34px;
height: 30px;
border-radius: 6px;
background: root.active
? Theme.accent
: (ta.has-hover ? Theme.surface-hover : Theme.surface-elevated);
genre-row := HorizontalLayout {
padding-left: 12px;
padding-right: 14px;
padding-left: 10px;
padding-right: 12px;
spacing: 7px;
VerticalLayout {
alignment: center;
QbzIcon {
source: @image-url("../assets/icons/list-filter.svg");
width: 14px;
height: 14px;
width: 13px;
height: 13px;
tint: root.active ? #ffffff : Theme.text-secondary;
}
}
@@ -329,7 +329,7 @@ component FavGenreButton inherits Rectangle {
: @tr("{} genres", GenreFilterState.selected-count))
: @tr("Filter by genre");
color: root.active ? #ffffff : Theme.text-secondary;
font-size: 13px;
font-size: 12px;
vertical-alignment: center;
}
}
@@ -344,8 +344,8 @@ component FavGenreButton inherits Rectangle {
// Grid/list segmented toggle (albums toolbar).
component ViewToggle inherits Rectangle {
width: 68px;
height: 34px;
width: 60px;
height: 30px;
border-radius: 6px;
background: Theme.surface-elevated;
clip: true;
@@ -353,6 +353,7 @@ component ViewToggle inherits Rectangle {
ToggleButton {
icon: @image-url("../assets/icons/layout-grid.svg");
active: FavoritesState.albums-view-mode == "grid";
sm: true;
clicked => {
FavoritesActions.albums-set-view("grid");
}
@@ -360,6 +361,7 @@ component ViewToggle inherits Rectangle {
ToggleButton {
icon: @image-url("../assets/icons/list.svg");
active: FavoritesState.albums-view-mode == "list";
sm: true;
clicked => {
FavoritesActions.albums-set-view("list");
}
@@ -505,6 +507,7 @@ export component FavoritesView inherits Rectangle {
alignment: center;
ExpandableSearch {
placeholder: @tr("Search");
sm: true;
query <=> FavoritesState.tracks-search;
edited(q) => {
FavoritesActions.search-tracks(q);
@@ -525,6 +528,7 @@ export component FavoritesView inherits Rectangle {
@tr("Group: Artist"),
@tr("Group: Name"),
];
sm: true;
current-index: FavoritesState.tracks-group-mode == "off" ? 0
: FavoritesState.tracks-group-mode == "album" ? 1
: FavoritesState.tracks-group-mode == "artist" ? 2
@@ -546,6 +550,7 @@ export component FavoritesView inherits Rectangle {
alignment: center;
ExpandableSearch {
placeholder: @tr("Search");
sm: true;
query <=> FavoritesState.albums-search;
edited(q) => {
FavoritesActions.albums-search(q);
@@ -565,6 +570,7 @@ export component FavoritesView inherits Rectangle {
@tr("Group: A-Z"),
@tr("Group: Artist"),
];
sm: true;
current-index: FavoritesState.albums-group-mode == "off" ? 0
: FavoritesState.albums-group-mode == "alpha" ? 1
: 2;
@@ -584,6 +590,7 @@ export component FavoritesView inherits Rectangle {
@tr("Title Z-A"),
@tr("Artist A-Z"),
];
sm: true;
current-index: FavoritesState.albums-sort-by == "default" ? 0
: FavoritesState.albums-sort-by == "title-asc" ? 1
: FavoritesState.albums-sort-by == "title-desc" ? 2
@@ -15,6 +15,8 @@ export component ExpandableSearch inherits Rectangle {
in property <length> max-open-width: 216px;
in-out property <bool> open: false;
in-out property <string> query;
// Bootstrap-style small variant. Default is the standard size.
in property <bool> sm: false;
callback edited(string);
changed open => {
@@ -24,20 +26,20 @@ export component ExpandableSearch inherits Rectangle {
}
// Closed footprint — just the magnifier slot.
width: 34px;
height: 34px;
width: root.sm ? 30px : 34px;
height: root.sm ? 30px : 34px;
// Closed: the magnifier toggle.
Rectangle {
visible: !root.open;
width: 34px;
height: 34px;
width: root.sm ? 30px : 34px;
height: root.sm ? 30px : 34px;
border-radius: 6px;
background: open-ta.has-hover ? Theme.surface-hover : transparent;
QbzIcon {
source: @image-url("../assets/icons/search.svg");
width: 16px;
height: 16px;
width: root.sm ? 14px : 16px;
height: root.sm ? 14px : 16px;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
tint: open-ta.has-hover ? Theme.text-primary : Theme.text-muted;
@@ -55,7 +57,7 @@ export component ExpandableSearch inherits Rectangle {
visible: root.open;
x: parent.width - self.width;
width: root.open ? root.max-open-width : 0px;
height: 34px;
height: root.sm ? 30px : 34px;
background: Theme.surface-card;
border-radius: 6px;
border-width: 1px;
@@ -110,8 +112,8 @@ export component ExpandableSearch inherits Rectangle {
horizontal-stretch: 0;
alignment: center;
Rectangle {
width: 24px;
height: 24px;
width: root.sm ? 22px : 24px;
height: root.sm ? 22px : 24px;
border-radius: 4px;
background: clear-ta.has-hover ? Theme.surface-elevated : transparent;
QbzIcon {
@@ -68,12 +68,15 @@ export component MultiSelectBar inherits Rectangle {
vertical-alignment: center;
horizontal-stretch: 1;
}
for act in root.actions: BulkButton {
label: act.label;
danger: act.danger;
enabled-when: !act.needs-selection || root.selected-count > 0;
clicked => {
root.action(act.id);
for act in root.actions: VerticalLayout {
alignment: center;
BulkButton {
label: act.label;
danger: act.danger;
enabled-when: !act.needs-selection || root.selected-count > 0;
clicked => {
root.action(act.id);
}
}
}
}
@@ -47,6 +47,9 @@ export component QbzSelect inherits Rectangle {
// option labels (device names). 0px keeps the list at `menu-width`.
in property <length> popup-width: 0px;
in property <bool> enabled: true;
// Bootstrap-style small variant. Default is the standard size (used by
// Settings); toolbars opt in with `sm: true`.
in property <bool> sm: false;
callback selected(int);
// Resolved width of the open list.
@@ -58,7 +61,7 @@ export component QbzSelect inherits Rectangle {
private property <length> header-height: 24px;
width: root.menu-width;
height: 34px;
height: root.sm ? 30px : 34px;
border-radius: Radius.sm;
border-width: 1px;
border-color: Theme.border-subtle;
@@ -66,8 +69,8 @@ export component QbzSelect inherits Rectangle {
opacity: root.enabled ? 1.0 : 0.4;
HorizontalLayout {
padding-left: 12px;
padding-right: 10px;
padding-left: root.sm ? 10px : 12px;
padding-right: root.sm ? 8px : 10px;
spacing: 8px;
Text {
text: root.current-index >= 0 && root.current-index < root.options.length
@@ -89,8 +92,8 @@ export component QbzSelect inherits Rectangle {
alignment: center;
QbzIcon {
source: @image-url("../assets/icons/chevron-down.svg");
width: 16px;
height: 16px;
width: root.sm ? 14px : 16px;
height: root.sm ? 14px : 16px;
tint: Theme.text-muted;
}
}
@@ -9,18 +9,20 @@ import { QbzIcon } from "QbzIcon.slint";
export component ToggleButton inherits Rectangle {
in property <image> icon;
in property <bool> active: false;
// Bootstrap-style small variant. Default is the standard size.
in property <bool> sm: false;
callback clicked();
width: 34px;
height: 34px;
width: root.sm ? 30px : 34px;
height: root.sm ? 30px : 34px;
background: root.active
? Theme.surface-hover
: (ta.has-hover ? Theme.surface-elevated : transparent);
QbzIcon {
source: root.icon;
width: 17px;
height: 17px;
width: root.sm ? 15px : 17px;
height: root.sm ? 15px : 17px;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
tint: root.active ? Theme.text-primary : Theme.text-muted;