Files
Tofu/ui/components/server-rail.slint
T
Inako 5eb47e45ef feat: implement client backend
This includes temporary AI-generated frontend scaffolding, none of this will be used in production. It was just used during development for the backend.
2026-10-09 19:46:02 +01:00

150 lines
4.6 KiB
Plaintext

/// TEMPORARY AI GENERATED FRONTEND \\\
/// NOT TO BE USED IN PRODUCTION \\\
import { ScrollView } from "std-widgets.slint";
import { Theme } from "../theme.slint";
import { Icons } from "../icons.slint";
import { ServerItem } from "../types.slint";
import { Icon } from "icon.slint";
import { Badge } from "badge.slint";
// One round button on the rail. Morphs from circle to rounded square on hover
// or selection, with a white "pill" on the left edge.
component RailButton inherits Rectangle {
in property <bool> selected;
in property <bool> unread;
in property <int> mentions;
in property <color> idle-color: Theme.chat-bg;
in property <color> active-color: Theme.accent;
callback clicked();
height: 56px;
// Left-edge pill: tall = selected, medium = hovered, dot = unread.
Rectangle {
x: 0px;
width: 4px;
height: root.selected ? 40px : (touch.has-hover ? 20px : (root.unread ? 8px : 0px));
y: (parent.height - self.height) / 2;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
background: Theme.text-header;
animate height { duration: 120ms; }
}
body := Rectangle {
width: 48px;
height: 48px;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
clip: true;
border-radius: root.selected || touch.has-hover ? 16px : 24px;
background: root.selected || touch.has-hover ? root.active-color : root.idle-color;
animate border-radius { duration: 120ms; }
@children
}
Badge {
count: root.mentions;
x: body.x + body.width - self.width + 4px;
y: body.y + body.height - self.height + 4px;
}
touch := TouchArea {
mouse-cursor: pointer;
clicked => {
root.clicked();
}
}
}
export component ServerRail inherits Rectangle {
in property <[ServerItem]> servers;
in property <string> selected-id; // "" = Home (direct messages)
in property <bool> home-unread;
in property <int> home-mentions;
callback select(string);
callback add-server();
width: Theme.rail-width;
background: Theme.rail-bg;
ScrollView {
vertical-scrollbar-policy: always-off;
horizontal-scrollbar-policy: always-off;
VerticalLayout {
padding-top: 8px;
padding-bottom: 8px;
alignment: start;
RailButton {
selected: root.selected-id == "";
unread: root.home-unread;
mentions: root.home-mentions;
clicked => {
root.select("");
}
Icon {
source: Icons.chat;
tint: white;
icon-size: 26px;
// `parent` here is the rail layout (children are projected into RailButton),
// so centre against the button's fixed 48px body instead.
x: (48px - self.width) / 2;
y: (48px - self.height) / 2;
}
}
// separator
Rectangle {
height: 10px;
Rectangle {
width: 32px;
height: 2px;
x: (parent.width - self.width) / 2;
y: 4px;
border-radius: 1px;
background: Theme.divider;
}
}
for s in root.servers: RailButton {
selected: root.selected-id == s.id;
unread: s.unread;
mentions: s.mentions;
idle-color: s.color;
active-color: s.color;
clicked => {
root.select(s.id);
}
Text {
width: 48px;
height: 48px;
text: s.initial;
color: white;
font-size: 20px;
font-weight: 600;
horizontal-alignment: center;
vertical-alignment: center;
}
}
RailButton {
idle-color: Theme.chat-bg;
active-color: Theme.success;
clicked => {
root.add-server();
}
Icon {
source: Icons.plus;
tint: Theme.success;
icon-size: 24px;
x: (48px - self.width) / 2;
y: (48px - self.height) / 2;
}
}
}
}
}