Put a scrollbar on the controls and shortcuts sheet

The gesture book runs to several screens inside a card that otherwise
looks complete. Same wrapping as the develop column. The bar is drawn
over the list's right edge, so it overlaps the last few pixels of each
"See it" button.
This commit is contained in:
2026-09-26 07:25:45 -04:00
parent f7df276295
commit cc905fa2ed
+78 -64
View File
@@ -22,7 +22,7 @@
// about what a gesture is.
import { Theme } from "theme.slint";
import { Button, Caption } from "widgets.slint";
import { Button, Caption, ScrollBar } from "widgets.slint";
// One line of the sheet: a section heading, or a gesture and its routes.
//
@@ -117,79 +117,93 @@ export component GestureSheet inherits Rectangle {
// The list scrolls; the title and the button do not, so a long
// vocabulary never pushes the way out off the bottom of the card.
Flickable {
vertical-stretch: 1;
viewport-width: self.width;
viewport-height: list.preferred-height;
Rectangle {
vertical-stretch: 1;
book-flick := Flickable {
width: parent.width;
height: parent.height;
viewport-width: self.width;
viewport-height: list.preferred-height;
list := VerticalLayout {
width: parent.viewport-width;
spacing: Theme.gap-sm;
alignment: start;
list := VerticalLayout {
width: parent.viewport-width;
spacing: Theme.gap-sm;
alignment: start;
for r[i] in root.rows: VerticalLayout {
spacing: 2px;
for r[i] in root.rows: VerticalLayout {
spacing: 2px;
// A heading and a gesture are the same row type, so
// each half is drawn under its own condition rather
// than by two repeaters over one filtered list — which
// would be two passes that could disagree about order.
// Space above a heading, and none above the first:
// the gap is what separates a section from the one
// before it, and there is nothing before the first.
//
// An empty Rectangle rather than a `y` offset on the
// heading — a child of a layout may not set its own
// `y`, because the layout is already setting it.
if r.heading != "" && i > 0: Rectangle {
height: Theme.gap;
}
if r.heading != "": Text {
text: r.heading;
color: Theme.ink-dim;
font-size: Theme.text-sm;
font-weight: 700;
}
// The title, and beside it "See it" where the manual
// shows the gesture. On the title's line rather than
// under the routes, so it is found while reading the
// title — the moment of "what does that look like?".
if r.heading == "": HorizontalLayout {
spacing: Theme.gap;
Text {
text: r.title;
color: Theme.ink;
font-size: Theme.text;
font-weight: 600;
wrap: word-wrap;
horizontal-stretch: 1;
vertical-alignment: center;
// A heading and a gesture are the same row type, so
// each half is drawn under its own condition rather
// than by two repeaters over one filtered list — which
// would be two passes that could disagree about order.
// Space above a heading, and none above the first:
// the gap is what separates a section from the one
// before it, and there is nothing before the first.
//
// An empty Rectangle rather than a `y` offset on the
// heading — a child of a layout may not set its own
// `y`, because the layout is already setting it.
if r.heading != "" && i > 0: Rectangle {
height: Theme.gap;
}
if r.manual != "": Button {
text: "See it";
accessible-label: "See " + r.title + " in the manual";
clicked => { root.open-manual(r.manual); }
if r.heading != "": Text {
text: r.heading;
color: Theme.ink-dim;
font-size: Theme.text-sm;
font-weight: 700;
}
}
if r.touch != "": Route {
modality: "Touch";
how: r.touch;
}
if r.pointer != "": Route {
modality: "Pointer";
how: r.pointer;
}
if r.keys != "": Route {
modality: "Keyboard";
how: r.keys;
// The title, and beside it "See it" where the manual
// shows the gesture. On the title's line rather than
// under the routes, so it is found while reading the
// title — the moment of "what does that look like?".
if r.heading == "": HorizontalLayout {
spacing: Theme.gap;
Text {
text: r.title;
color: Theme.ink;
font-size: Theme.text;
font-weight: 600;
wrap: word-wrap;
horizontal-stretch: 1;
vertical-alignment: center;
}
if r.manual != "": Button {
text: "See it";
accessible-label: "See " + r.title + " in the manual";
clicked => { root.open-manual(r.manual); }
}
}
if r.touch != "": Route {
modality: "Touch";
how: r.touch;
}
if r.pointer != "": Route {
modality: "Pointer";
how: r.pointer;
}
if r.keys != "": Route {
modality: "Keyboard";
how: r.keys;
}
}
}
}
// A bar for a pointer: the book runs to several screens, and the bar is
// what says so on a card that otherwise looks complete.
ScrollBar {
x: parent.width - self.width;
y: 0px;
viewport-y <=> book-flick.viewport-y;
viewport-height: book-flick.viewport-height;
visible-height: book-flick.height;
}
}
HorizontalLayout {