init
This commit is contained in:
102
ui/components/button.slint
Normal file
102
ui/components/button.slint
Normal file
@@ -0,0 +1,102 @@
|
||||
// Button Component
|
||||
// Shadcn-style button with multiple variants and sizes
|
||||
|
||||
import { Theme, Typography, SpacingSystem } from "../theme/theme.slint";
|
||||
import { Animations } from "../utils/animations.slint";
|
||||
|
||||
export component Button {
|
||||
// Public properties
|
||||
in property <string> text: "Button";
|
||||
in property <string> variant: "default"; // default | destructive | outline | secondary | ghost
|
||||
in property <string> size: "md"; // sm | md | lg
|
||||
in property <bool> disabled: false;
|
||||
|
||||
// Callbacks
|
||||
callback clicked();
|
||||
|
||||
// Internal state
|
||||
private property <bool> hovered: false;
|
||||
|
||||
// Calculate background color based on variant
|
||||
private property <color> base-bg-color: {
|
||||
if disabled { Theme.colors.muted }
|
||||
else if variant == "destructive" { Theme.colors.destructive }
|
||||
else if variant == "outline" { Colors.transparent }
|
||||
else if variant == "secondary" { Theme.colors.secondary }
|
||||
else if variant == "ghost" { Colors.transparent }
|
||||
else { Theme.colors.primary }
|
||||
};
|
||||
|
||||
// Calculate hover background color
|
||||
private property <color> hover-bg-color: {
|
||||
if disabled { Theme.colors.muted }
|
||||
else if variant == "destructive" { #dc2626 }
|
||||
else if variant == "outline" { Theme.colors.accent }
|
||||
else if variant == "secondary" { #e4e4e7 }
|
||||
else if variant == "ghost" { Theme.colors.accent }
|
||||
else { #27272a }
|
||||
};
|
||||
|
||||
// Calculate text color based on variant
|
||||
private property <color> text-color: {
|
||||
if disabled { Theme.colors.muted-foreground }
|
||||
else if variant == "destructive" { Theme.colors.destructive-foreground }
|
||||
else if variant == "outline" { Theme.colors.foreground }
|
||||
else if variant == "secondary" { Theme.colors.secondary-foreground }
|
||||
else if variant == "ghost" { Theme.colors.foreground }
|
||||
else { Theme.colors.primary-foreground }
|
||||
};
|
||||
|
||||
// Calculate size-based dimensions
|
||||
private property <length> btn-height: size == "sm" ? 36px : size == "lg" ? 44px : 40px;
|
||||
private property <length> btn-padding-x: size == "sm" ? 12px : size == "lg" ? 24px : 16px;
|
||||
private property <length> font-size: size == "sm" ? Typography.sizes.sm : size == "lg" ? Typography.sizes.lg : Typography.sizes.base;
|
||||
|
||||
min-width: btn-height;
|
||||
min-height: btn-height;
|
||||
|
||||
// Main container
|
||||
container := Rectangle {
|
||||
background: hovered ? hover-bg-color : base-bg-color;
|
||||
border-radius: SpacingSystem.radius.md;
|
||||
border-width: variant == "outline" ? 1px : 0px;
|
||||
border-color: Theme.colors.border;
|
||||
|
||||
// Smooth transitions
|
||||
animate background {
|
||||
duration: Animations.durations.fast;
|
||||
easing: Animations.ease-in-out;
|
||||
}
|
||||
|
||||
// Content layout
|
||||
HorizontalLayout {
|
||||
padding-left: btn-padding-x;
|
||||
padding-right: btn-padding-x;
|
||||
spacing: SpacingSystem.spacing.s2;
|
||||
alignment: center;
|
||||
|
||||
// Button text
|
||||
Text {
|
||||
text: root.text;
|
||||
color: text-color;
|
||||
font-size: font-size;
|
||||
font-weight: Typography.weights.medium;
|
||||
vertical-alignment: center;
|
||||
horizontal-alignment: center;
|
||||
}
|
||||
}
|
||||
|
||||
// Touch interaction area
|
||||
TouchArea {
|
||||
enabled: !disabled;
|
||||
|
||||
clicked => {
|
||||
root.clicked();
|
||||
}
|
||||
|
||||
moved => {
|
||||
hovered = self.has-hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user