import { LineEdit, ComboBox } from "std-widgets.slint";
// List item component
export component ListItem inherits Rectangle {
in property <string> label;
in property <bool> active: false;
callback clicked();
height: 40px;
background: active ? #e7f5ff : transparent;
border-radius: 4px;
HorizontalLayout {
padding-left: 12px;
padding-right: 12px;
alignment: start;
Text {
text: label;
font-size: 14px;
color: active ? #1971c2 : #495057;
font-weight: active ? 500 : 400;
vertical-alignment: center;
}
}
TouchArea {
clicked => { root.clicked(); }
}
}
export component Breadcrumb inherits Rectangle {
in property <[string]> path: [];
height: 32px;
background: #f8f9fa;
border-radius: 4px;
border-width: 1px;
border-color: #dee2e6;
HorizontalLayout {
padding-left: 12px;
padding-right: 12px;
spacing: 8px;
alignment: start;
for item[i] in path : HorizontalLayout {
spacing: 8px;
Text {
text: item;
font-size: 13px;
font-weight: (i == path.length - 1) ? 600 : 400;
color: (i == path.length - 1) ? #212529 : #868e96;
vertical-alignment: center;
}
if i < path.length - 1 : Text {
text: ">";
font-size: 13px;
color: #dee2e6;
vertical-alignment: center;
}
}
}
}
// Vertical divider
export component Divider inherits Rectangle {
width: 1px;
background: #dee2e6;
}
// Section header
export component SectionHeader inherits Rectangle {
in property <string> title;
height: 48px;
HorizontalLayout {
padding: 12px;
alignment: start;
Text {
text: title;
font-size: 18px;
font-weight: 600;
color: #212529;
vertical-alignment: center;
}
}
}
// Styled select/combo box
export component StyledComboBox inherits Rectangle {
in-out property <string> current-value;
in property <[string]> model;
in property <bool> enabled: true;
callback selected(string);
height: 36px;
width: root.preferred-width;
background: enabled ? #ffffff : #f8f9fa;
border-width: 1px;
border-color: #ced4da;
border-radius: 6px;
HorizontalLayout {
padding: 2px;
alignment: start;
combo := ComboBox {
current-value <=> root.current-value;
model: root.model;
enabled: root.enabled;
selected(val) => { root.selected(val); }
}
}
}
// Paper-like card component
export component Paper inherits Rectangle {
in property <bool> with-border: true;
in property <color> bg: #f8f9fa;
background: bg;
border-width: with-border ? 1px : 0px;
border-color: #dee2e6;
border-radius: 8px;
drop-shadow-blur: 4px;
drop-shadow-color: #00000010;
drop-shadow-offset-y: 1px;
}
// Form field with label
export component FormField inherits VerticalLayout {
in property <string> label;
in property <bool> required: false;
in property <string> error-message: "";
spacing: 4px;
HorizontalLayout {
spacing: 4px;
Text {
text: label;
font-size: 14px;
font-weight: 500;
color: error-message != "" ? #fa5252 : #212529;
}
if required : Text {
text: "*";
font-size: 14px;
color: #fa5252;
}
// spacer
Rectangle {
horizontal-stretch: 1;
}
}
@children
if error-message != "" : Text {
text: error-message;
font-size: 12px;
color: #fa5252;
}
}
// Styled text input
export component StyledLineEdit inherits Rectangle {
in-out property <string> text;
in property <string> placeholder;
in property <bool> enabled: true;
in property <bool> has-error: false;
callback edited(string);
height: 36px;
width: root.preferred-width;
background: enabled ? #ffffff : #f8f9fa;
border-width: 1px;
border-color: has-error ? #fa5252 : (input.has-focus ? #228be6 : #ced4da);
border-radius: 6px;
HorizontalLayout {
padding: 2px;
alignment: start;
input := LineEdit {
text <=> root.text;
placeholder-text: placeholder;
enabled: root.enabled;
edited(text) => {
root.edited(text);
}
}
}
}
// Alert component for messages (errors, info, etc.)
export component Alert inherits Rectangle {
in property <string> message;
in property <string> title: "Error";
in property <color> alert-color: #fa5252;
in property <color> bg-color: #fff5f5;
background: bg-color;
border-width: 1px;
border-color: alert-color;
border-radius: 8px;
min-height: 48px;
HorizontalLayout {
padding: 12px;
spacing: 12px;
Rectangle {
width: 4px;
background: alert-color;
border-radius: 2px;
}
VerticalLayout {
spacing: 4px;
alignment: center;
Text {
text: title;
font-size: 14px;
font-weight: 600;
color: alert-color;
}
Text {
text: message;
font-size: 14px;
color: #495057;
wrap: word-wrap;
}
}
}
}
// Custom StyledButton component
export component StyledButton inherits Rectangle {
in property <string> text: "";
in property <bool> primary: false;
in property <bool> flat: false;
in property <bool> outline: false;
in property <color> bg-color: flat ? #ffffff : (primary ? #228be6 : (outline ? transparent : #e9ecef));
in property <color> btn-border-color: flat ? #ffffff : (primary ? #228be6 : #ced4da);
in property <color> text-color: primary ? #ffffff : (outline ? (bg-color == transparent ? #495057 : bg-color) : #495057);
in property <bool> enabled: true;
callback clicked();
min-width: 80px;
min-height: 36px;
border-radius: 6px;
background: outline ? transparent : (touch.pressed ? bg-color.darker(0.2) : (touch.has-hover ? bg-color.darker(0.1) : bg-color));
border-width: 1px;
border-color: touch.has-hover ? btn-border-color.darker(0.1) : btn-border-color;
opacity: enabled ? 1.0 : 0.5;
touch := TouchArea {
enabled: root.enabled;
mouse-cursor: enabled ? pointer : default;
clicked => { root.clicked(); }
}
HorizontalLayout {
padding: 8px;
padding-left: 16px;
padding-right: 16px;
alignment: center;
Text {
text: text;
font-size: 14px;
font-weight: 500;
color: outline ? (bg-color == transparent ? #495057 : bg-color) : text-color;
vertical-alignment: center;
horizontal-alignment: center;
}
}
}
export component DocLink inherits Rectangle {
in property <string> label;
in property <string> url;
in property <string> description;
callback clicked();
min-height: 48px;
background: touch.pressed ? #e9ecef : (touch.has-hover ? #f1f3f5 : transparent);
border-radius: 4px;
touch := TouchArea {
clicked => {
root.clicked();
}
}
VerticalLayout {
padding-left: 8px;
padding-right: 8px;
padding-top: 4px;
padding-bottom: 4px;
alignment: center;
spacing: 2px;
Text {
text: label;
font-size: 14px;
font-weight: 600;
color: #228be6;
}
Text {
text: description;
font-size: 12px;
color: #868e96;
wrap: word-wrap;
}
}
}