import { ListView, HorizontalBox, VerticalBox } from "std-widgets.slint"; import { Palette } from "../globals/palette.slint"; struct SideBarItemData { text: string, selected: bool, has-focus: bool, } export component SideBar inherits Rectangle { in property title: label.text; in property <[string]> model: []; out property current-item: 0; out property current-focused: fs.has-focus ? fs.focused-tab : -1; callback item-selected(int); forward-focus: fs; accessible-role: tab; accessible-delegate-focus: current-focused >= 0 ? current-focused : current-item; Rectangle { background: Palette.background.darker(0.2); fs := FocusScope { property focused-tab: 0; x: 0; width: 0; key-pressed(event) => { if (event.text == "\n") { root.current-item = root.current-focused; return accept; } if (event.text == Key.UpArrow) { self.focused-tab = Math.max(self.focused-tab - 1, 0); return accept; } if (event.text == Key.DownArrow) { self.focused-tab = Math.min(self.focused-tab + 1, root.model.length - 1); return accept; } return reject; } key-released(event) => { if (event.text == " ") { root.current-item = root.current-focused; item-selected(root.current-item); return accept; } return reject; } } } VerticalLayout { padding: 0px; alignment: start; label := Text { font-size: 16px; horizontal-alignment: center; } ListView { height: 100%; for data[index] in root.model: Rectangle { Rectangle { width: 100%; height: 100%; background: Palette.background; opacity: touch.pressed ? 0.8 : touch.has-hover ? 0.6 : index == root.current-item ? 1.0 : index == root.current-focused ? 0.8 : 0; animate opacity { duration: 150ms; } } HorizontalBox { padding: 16px; spacing: 0px; Text { text: data; vertical-alignment: center; color: index == root.current-item ? Palette.primary : Palette.text-primary; } } touch := TouchArea { width: 100%; height: 100%; clicked => { root.current-item = index; item-selected(root.current-item); } } } } VerticalLayout { bottom := VerticalBox { padding-top: 0px; padding-bottom: 0px; @children } } } }