init
This commit is contained in:
148
ui/components/toast.slint
Normal file
148
ui/components/toast.slint
Normal file
@@ -0,0 +1,148 @@
|
||||
// Toast Component
|
||||
// Notification toast with auto-dismiss and animations
|
||||
|
||||
import { Theme, Typography, SpacingSystem } from "../theme/theme.slint";
|
||||
import { Animations } from "../utils/animations.slint";
|
||||
|
||||
// Toast message structure
|
||||
export struct ToastMessage {
|
||||
message: string,
|
||||
variant: string, // default | success | error | warning
|
||||
show: bool,
|
||||
}
|
||||
|
||||
// Single toast item
|
||||
export component Toast {
|
||||
// Public properties
|
||||
in property <string> message: "";
|
||||
in property <string> variant: "default"; // default | success | error | warning
|
||||
in-out property <bool> show: false;
|
||||
|
||||
// Callbacks
|
||||
callback dismissed();
|
||||
|
||||
// Calculate colors based on variant
|
||||
private property <color> bg-color: {
|
||||
if variant == "success" { #10b981 }
|
||||
else if variant == "error" { Theme.colors.destructive }
|
||||
else if variant == "warning" { #f59e0b }
|
||||
else { Theme.colors.card }
|
||||
};
|
||||
|
||||
private property <color> text-color: {
|
||||
if variant == "success" { #ffffff }
|
||||
else if variant == "error" { Theme.colors.destructive-foreground }
|
||||
else if variant == "warning" { #ffffff }
|
||||
else { Theme.colors.card-foreground }
|
||||
};
|
||||
|
||||
private property <string> icon: {
|
||||
if variant == "success" { "✓" }
|
||||
else if variant == "error" { "✕" }
|
||||
else if variant == "warning" { "⚠" }
|
||||
else { "ℹ" }
|
||||
};
|
||||
|
||||
// Animation properties
|
||||
property <length> translate-y: show ? 0px : -20px;
|
||||
property <float> opacity-val: show ? 1.0 : 0.0;
|
||||
|
||||
animate translate-y, opacity-val {
|
||||
duration: Animations.durations.normal;
|
||||
easing: Animations.ease-out;
|
||||
}
|
||||
|
||||
width: 350px;
|
||||
height: show ? 60px : 0px;
|
||||
|
||||
if show: Rectangle {
|
||||
y: translate-y;
|
||||
opacity: opacity-val;
|
||||
background: bg-color;
|
||||
border-radius: SpacingSystem.radius.lg;
|
||||
border-width: 1px;
|
||||
border-color: Theme.colors.border;
|
||||
drop-shadow-blur: 10px;
|
||||
drop-shadow-color: #00000020;
|
||||
drop-shadow-offset-y: 4px;
|
||||
|
||||
HorizontalLayout {
|
||||
padding: SpacingSystem.spacing.s4;
|
||||
spacing: SpacingSystem.spacing.s3;
|
||||
alignment: space-between;
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: SpacingSystem.spacing.s3;
|
||||
|
||||
// Icon
|
||||
Text {
|
||||
text: icon;
|
||||
font-size: Typography.sizes.xl;
|
||||
color: text-color;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
|
||||
// Message
|
||||
Text {
|
||||
text: message;
|
||||
font-size: Typography.sizes.base;
|
||||
color: text-color;
|
||||
vertical-alignment: center;
|
||||
wrap: word-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
// Close button
|
||||
Rectangle {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: SpacingSystem.radius.sm;
|
||||
background: close-touch.has-hover ? #00000020 : Colors.transparent;
|
||||
|
||||
animate background {
|
||||
duration: Animations.durations.fast;
|
||||
easing: Animations.ease-in-out;
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "✕";
|
||||
font-size: Typography.sizes.sm;
|
||||
color: text-color;
|
||||
horizontal-alignment: center;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
|
||||
close-touch := TouchArea {
|
||||
clicked => {
|
||||
root.dismissed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Toast container (manages multiple toasts)
|
||||
export component ToastContainer {
|
||||
in property <[ToastMessage]> toasts: [];
|
||||
|
||||
callback toast-dismissed(int);
|
||||
|
||||
// Position at top-right corner
|
||||
width: 370px;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: SpacingSystem.spacing.s2;
|
||||
alignment: start;
|
||||
|
||||
for toast[index] in toasts: Toast {
|
||||
message: toast.message;
|
||||
variant: toast.variant;
|
||||
show: toast.show;
|
||||
|
||||
dismissed => {
|
||||
root.toast-dismissed(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user