fix(slint): center the header search field on the window

The three header columns shared free space by stretch but kept their
own preferred widths, so the wide tab row pushed the center column —
and the search field with it — off true window center. Anchor the
tabs left and the user element right, and position the search field
absolutely at the window center instead.

cc
This commit is contained in:
vicrodh committed 2026-05-18 17:17:31 -06:00
1 parent 5d78fb0a09
commit a9d5f8d30d
1 file changed
+101 -113
+101 -113
View File
@@ -1,9 +1,12 @@
// Top header bar — three equal sections: navigation tabs (left), the
// search field (center, so it lands at the window center), and the user
// element with its dropdown menu (right).
// Top header bar — navigation tabs anchored left, the user element
// anchored right, and the search field absolutely centered on the window.
//
// The search field is positioned at the true window center (not inside a
// layout column) so it stays centered regardless of how wide the tab row
// or the user element become.
//
// Responsive: below the first breakpoint the tabs drop their icons;
// below the second the search field narrows to 70%.
// below the second the search field narrows.
import { Theme } from "../foundation/semantic-colors.slint";
import { Spacing } from "../foundation/spacing.slint";
@@ -21,11 +24,12 @@ component NavTab inherits Rectangle {
callback clicked();
height: 30px;
width: tab-row.preferred-width;
border-radius: Radius.sm;
background: root.active ? Theme.surface-elevated
: ta.has-hover ? Theme.surface-hover : transparent;
HorizontalLayout {
tab-row := HorizontalLayout {
padding-left: root.show-icon ? 9px : 11px;
padding-right: 11px;
spacing: 6px;
@@ -104,121 +108,105 @@ export component HeaderBar inherits Rectangle {
property <bool> show-tab-icons: root.width >= 1140px;
property <length> search-width: root.width < 960px ? 224px : 320px;
HorizontalLayout {
// --- Tabs (left third) -------------------------------------------
VerticalLayout {
horizontal-stretch: 1;
alignment: center;
HorizontalLayout {
padding-left: Spacing.md;
spacing: Spacing.xs;
alignment: start;
NavTab {
icon: @image-url("../assets/icons/compass.svg");
label: "Discover";
active: true;
show-icon: root.show-tab-icons;
}
NavTab {
icon: @image-url("../assets/icons/library-big.svg");
label: "Library";
show-icon: root.show-tab-icons;
}
NavTab {
icon: @image-url("../assets/icons/hard-drive.svg");
label: "Local Library";
show-icon: root.show-tab-icons;
}
NavTab {
icon: @image-url("../assets/icons/cassette-tape.svg");
label: "My QBZ";
show-icon: root.show-tab-icons;
}
}
// --- Tabs (anchored left) ----------------------------------------------
tabs := HorizontalLayout {
x: Spacing.md;
y: (root.height - self.height) / 2;
height: 30px;
spacing: Spacing.xs;
NavTab {
icon: @image-url("../assets/icons/compass.svg");
label: "Discover";
active: true;
show-icon: root.show-tab-icons;
}
NavTab {
icon: @image-url("../assets/icons/library-big.svg");
label: "Library";
show-icon: root.show-tab-icons;
}
NavTab {
icon: @image-url("../assets/icons/hard-drive.svg");
label: "Local Library";
show-icon: root.show-tab-icons;
}
NavTab {
icon: @image-url("../assets/icons/cassette-tape.svg");
label: "My QBZ";
show-icon: root.show-tab-icons;
}
}
// --- Search (center third) ---------------------------------------
VerticalLayout {
horizontal-stretch: 1;
alignment: center;
HorizontalLayout {
// --- Search (absolutely centered on the window) ------------------------
Rectangle {
x: (root.width - self.width) / 2;
y: (root.height - self.height) / 2;
width: root.search-width;
height: 32px;
border-radius: 6px;
border-width: 1px;
border-color: Theme.border-subtle;
background: Theme.surface-elevated;
HorizontalLayout {
padding-left: 10px;
padding-right: 10px;
spacing: 7px;
VerticalLayout {
alignment: center;
Rectangle {
width: root.search-width;
height: 32px;
border-radius: 6px;
border-width: 1px;
border-color: Theme.border-subtle;
background: Theme.surface-elevated;
HorizontalLayout {
padding-left: 10px;
padding-right: 10px;
spacing: 7px;
VerticalLayout {
alignment: center;
QbzIcon {
source: @image-url("../assets/icons/search.svg");
width: 14px;
height: 14px;
tint: Theme.text-muted;
}
}
Text {
text: @tr("Search");
color: Theme.text-muted;
font-size: 13px;
vertical-alignment: center;
horizontal-stretch: 1;
}
}
QbzIcon {
source: @image-url("../assets/icons/search.svg");
width: 14px;
height: 14px;
tint: Theme.text-muted;
}
}
Text {
text: @tr("Search");
color: Theme.text-muted;
font-size: 13px;
vertical-alignment: center;
horizontal-stretch: 1;
}
}
}
// --- User element (right third) ----------------------------------
VerticalLayout {
horizontal-stretch: 1;
alignment: center;
HorizontalLayout {
padding-right: Spacing.md;
alignment: end;
user-area := TouchArea {
width: user-row.preferred-width + 16px;
height: 36px;
mouse-cursor: pointer;
clicked => {
menu.show();
}
Rectangle {
width: 100%;
height: 100%;
border-radius: Radius.sm;
background: user-area.has-hover ? Theme.surface-hover : transparent;
}
user-row := HorizontalLayout {
x: 8px;
height: parent.height;
spacing: 9px;
VerticalLayout {
alignment: center;
Text {
text: SessionState.user-name == ""
? @tr("Guest")
: SessionState.user-name;
color: Theme.text-primary;
font-size: Typography.body;
}
}
VerticalLayout {
alignment: center;
QbzIcon {
source: @image-url("../assets/icons/menu.svg");
width: 18px;
height: 18px;
tint: Theme.text-secondary;
}
}
}
// --- User element (anchored right) -------------------------------------
user-area := TouchArea {
x: root.width - self.width - Spacing.md;
y: (root.height - self.height) / 2;
width: user-row.preferred-width + 16px;
height: 36px;
mouse-cursor: pointer;
clicked => {
menu.show();
}
Rectangle {
width: 100%;
height: 100%;
border-radius: Radius.sm;
background: user-area.has-hover ? Theme.surface-hover : transparent;
}
user-row := HorizontalLayout {
x: 8px;
height: parent.height;
spacing: 9px;
VerticalLayout {
alignment: center;
Text {
text: SessionState.user-name == ""
? @tr("Guest")
: SessionState.user-name;
color: Theme.text-primary;
font-size: Typography.body;
}
}
VerticalLayout {
alignment: center;
QbzIcon {
source: @image-url("../assets/icons/menu.svg");
width: 18px;
height: 18px;
tint: Theme.text-secondary;
}
}
}