feat(slint): split sidebar toggle from nav buttons, animate side panels

NavButtons now renders the collapse toggle and history buttons as two
spaced pills instead of separating them with a bar. Queue and Lyrics
sidebars animate their own width open/closed (160ms ease-in-out) so
they slide in like the main sidebar instead of appearing abruptly.

cc
This commit is contained in:
vicrodh committed 2026-05-18 22:43:13 -06:00
1 parent 7e6e548598
commit 1f6159f3ba
4 files changed
+57 -38

No files matched your search

+5 -4
View File
@@ -108,10 +108,11 @@ export component AppShell inherits Rectangle {
} }
} }
// Right-side panel — a layout sibling of the content area, // Right-side panels — layout siblings of the content area, so
// so it shrinks the content rather than overlaying it. // they shrink the content rather than overlaying it. Always
if ShellState.right-panel == 1: QueueSidebar { } // present; each animates its own width open/closed.
if ShellState.right-panel == 2: LyricsSidebar { } QueueSidebar { }
LyricsSidebar { }
} }
PlayerBar { PlayerBar {
@@ -37,7 +37,11 @@ component CloseButton inherits Rectangle {
} }
export component LyricsSidebar inherits Rectangle { export component LyricsSidebar inherits Rectangle {
width: 320px; // Always present; the width animates 0 <-> 320 so the panel slides
// in smoothly, matching the left sidebar's collapse animation.
width: ShellState.right-panel == 2 ? 320px : 0px;
clip: true;
animate width { duration: 160ms; easing: ease-in-out; }
background: Theme.surface-card; background: Theme.surface-card;
VerticalLayout { VerticalLayout {
+42 -32
View File
@@ -1,9 +1,9 @@
// Browser-like back / forward navigation pair. // Sidebar-collapse toggle + browser-like back / forward navigation pair.
// //
// Same visual format as the Discover tab pill group (an elevated rounded // Two separate elevated pills with a gap between them: the sidebar
// container). Used inline beside the Discover tabs and in place of the // toggle stands on its own, the [<] [>] history pair is its own group.
// per-page Back button. Both buttons drive the NavState global, so the // Used inline beside the Discover tabs and in place of the per-page
// Rust nav history records every move. // Back button.
import { Theme } from "../foundation/semantic-colors.slint"; import { Theme } from "../foundation/semantic-colors.slint";
import { NavState, ShellState } from "../state.slint"; import { NavState, ShellState } from "../state.slint";
@@ -39,40 +39,50 @@ component NavBtn inherits Rectangle {
} }
} }
export component NavButtons inherits Rectangle { // One elevated rounded pill wrapping its NavBtn children.
component NavPill inherits Rectangle {
background: Theme.surface-elevated; background: Theme.surface-elevated;
border-radius: 6px; border-radius: 6px;
width: btn-row.preferred-width;
height: 34px; height: 34px;
@children
}
btn-row := HorizontalLayout { export component NavButtons inherits HorizontalLayout {
padding: 3px; spacing: 8px;
spacing: 4px;
// Leading button: collapses / expands the left sidebar. Lives // Sidebar collapse toggle — its own pill.
// here so it appears just left of the [<] [>] pair in every view. NavPill {
NavBtn { width: collapse-row.preferred-width;
icon: @image-url("../assets/icons/panel-left.svg"); collapse-row := HorizontalLayout {
clicked => { padding: 3px;
ShellState.sidebar-collapsed = !ShellState.sidebar-collapsed; NavBtn {
icon: @image-url("../assets/icons/panel-left.svg");
clicked => {
ShellState.sidebar-collapsed = !ShellState.sidebar-collapsed;
}
} }
} }
// 1px separator between the collapse button and the history pair. }
Rectangle {
width: 1px; // Back / forward history pair — its own pill.
background: Theme.border-subtle; NavPill {
} width: history-row.preferred-width;
NavBtn { history-row := HorizontalLayout {
icon: @image-url("../assets/icons/chevron-left.svg"); padding: 3px;
enabled: NavState.can-back; spacing: 4px;
clicked => { NavBtn {
NavState.request-back(); icon: @image-url("../assets/icons/chevron-left.svg");
enabled: NavState.can-back;
clicked => {
NavState.request-back();
}
} }
} NavBtn {
NavBtn { icon: @image-url("../assets/icons/chevron-right.svg");
icon: @image-url("../assets/icons/chevron-right.svg"); enabled: NavState.can-forward;
enabled: NavState.can-forward; clicked => {
clicked => { NavState.request-forward();
NavState.request-forward(); }
} }
} }
} }
+5 -1
View File
@@ -110,7 +110,11 @@ component QueueRow inherits Rectangle {
} }
export component QueueSidebar inherits Rectangle { export component QueueSidebar inherits Rectangle {
width: 320px; // Always present; the width animates 0 <-> 320 so the panel slides
// in smoothly, matching the left sidebar's collapse animation.
width: ShellState.right-panel == 1 ? 320px : 0px;
clip: true;
animate width { duration: 160ms; easing: ease-in-out; }
background: Theme.surface-card; background: Theme.surface-card;
VerticalLayout { VerticalLayout {