Files
shadcn-slint/ui/pages/profiles.slint
2026-01-30 12:56:00 +08:00

205 lines
6.2 KiB
Plaintext

import { Theme, SpacingSystem, Typography } from "../theme/theme.slint";
import { Card } from "../components/card.slint";
import { Button } from "../components/button.slint";
import { Badge } from "../components/badge.slint";
import { Progress } from "../components/progress.slint";
export struct ProfileData {
id: string,
name: string,
type: string, // "local" or "remote"
description: string,
usage: float, // For remote profiles
total: float, // For remote profiles
updated: string,
}
export component ProfilesPage {
in property <[ProfileData]> profiles: [];
in property <string> selected-profile-id: "";
callback add-profile();
callback refresh-all();
callback select-profile(string);
callback edit-profile(string);
callback delete-profile(string);
callback refresh-profile(string);
VerticalLayout {
padding: SpacingSystem.spacing.s4;
spacing: SpacingSystem.spacing.s4;
// Header
HorizontalLayout {
spacing: SpacingSystem.spacing.s3;
alignment: space-between;
Text {
text: "Profiles";
color: Theme.colors.foreground;
font-size: Typography.sizes.xl;
font-weight: Typography.weights.bold;
vertical-alignment: center;
}
HorizontalLayout {
spacing: SpacingSystem.spacing.s2;
Button {
text: "+";
variant: "ghost";
clicked => {
root.add-profile();
}
}
Button {
text: "↻";
variant: "ghost";
clicked => {
root.refresh-all();
}
}
}
}
// Profile Grid
ScrollView {
GridLayout {
spacing: SpacingSystem.spacing.s3;
for profile in root.profiles: ProfileItem {
profile-data: profile;
selected: profile.id == root.selected-profile-id;
clicked => {
root.select-profile(profile.id);
}
refresh-clicked => {
root.refresh-profile(profile.id);
}
}
}
}
}
}
component ProfileItem {
in property <ProfileData> profile-data;
in property <bool> selected: false;
callback clicked();
callback refresh-clicked();
private property <bool> hovered: false;
min-width: 288px; // 18rem
height: 96px;
states [
selected when root.selected: {
container.border-color: Theme.colors.primary.transparentize(0.5);
container.background: Theme.colors.accent.transparentize(0.4);
}
]
container := Card {
border-width: 2px;
VerticalLa spacing: SpacingSystem.spacing.s2;
// Header
HorizontalLayout {
spacing: SpacingSystem.spacing.s2;
alignment: space-between;
HorizontalLayout {
spacing: SpacingSystem.spacing.s2;
Text {
text: root.profile-data.type == "remote" ? "☁" : "📄";
font-size: Typography.sizes.lg;
vertical-alignment: center;
}
{
text: root.profile-data.name;
color: Theme.colors.foreground;
font-size: Typography.sizes.base;
font-weight: Typography.weights.semibold;
vertical-alignment: center;
}
}
if root.profile-data.type == "remote": Button {
width: 24px;
height: 24px;
text: "↻";
variant: "ghost";
clicked => {
root.refresh-clicked();
}
}
}
// Description
Text {
text: root.profile-data.description;
color: Theme.colors.muted-foreground;
font-size: Typography.sizes.xs;
overflow: elide;
}
// Progress bar for remote profiles
if root.profile-data.type == "remote": VerticalLayout {
spacing: SpacingSystem.spacing.s1;
Progress {
value: (root.profile-data.usage / root.profile-data.total) * 100;
}
HorizontalLayout {
alignment: space-between;
Text {
text: "Updated: " + root.profile-data.updated;
color: Theme.colors.muted-foreground;
font-size: 10px;
}
Text {
text: root.profile-data.usage + " / " + root.profile-data.total + " GB";
color: Theme.colors.oreground;
font-size: 10px;
}
}
}
// Local profile info
if root.profile-data.type == "local": HorizontalLayout {
alignment: space-between;
Text {
text: "Local Profile";
color: Theme.colors.muted-foreground;
font-size: 10px;
}
}
}
touch := TouchArea {
clicked => {
root.clicked();
}
moved => {
root.hovered = self.has-hover;
}
}
}
}