mirror of
https://github.com/flectar/mail.git
synced 2026-11-11 17:57:54 +00:00
96 lines
4.0 KiB
Plaintext
96 lines
4.0 KiB
Plaintext
import { HorizontalBox } from "std-widgets.slint";
|
|
import { AppTheme, LayoutMetrics, ThemeUtilities } from "../design-system.slint";
|
|
import { TypeScale } from "../typography.slint";
|
|
import { FocusVisibleScope } from "focus-visible-scope.slint";
|
|
|
|
// Application-owned button with deterministic geometry across compositors.
|
|
export component Button inherits Rectangle {
|
|
in property <string> text;
|
|
in property <image> icon;
|
|
in property <bool> has-icon: false;
|
|
in property <bool> colorize-icon: true;
|
|
in property <length> icon-size: LayoutMetrics.icon-size;
|
|
in property <bool> primary: false;
|
|
in property <bool> destructive: false;
|
|
in property <bool> selected: false;
|
|
in property <bool> enabled: true;
|
|
// A button that fills a fixed-width column may elide a label that does
|
|
// not fit there; other buttons are given room for the whole label.
|
|
in property <TextOverflow> label-overflow: clip;
|
|
// The width that shows the whole label, for buttons sized to it. The
|
|
// label row moves when pressed, so it does not size the button itself.
|
|
out property <length> content-width: label-row.preferred-width;
|
|
out property <bool> focus-visible: keyboard.focus-visible;
|
|
callback clicked;
|
|
|
|
height: 32px;
|
|
min-width: 64px;
|
|
border-radius: LayoutMetrics.corner-radius - 2px;
|
|
forward-focus: keyboard;
|
|
border-width: keyboard.focus-visible ? 2px : root.primary || root.destructive ? 0px : 1px;
|
|
border-color: keyboard.focus-visible || root.selected ? AppTheme.accent : AppTheme.control-border;
|
|
private property <color> fill-color: !root.enabled ? AppTheme.disabled-bg
|
|
: root.destructive ? (button-area.pressed ? AppTheme.destructive-pressed : button-area.has-hover ? AppTheme.destructive-hover : AppTheme.destructive)
|
|
: root.primary ? (button-area.pressed ? AppTheme.primary-pressed : button-area.has-hover ? AppTheme.primary-hover : AppTheme.primary)
|
|
: root.selected ? AppTheme.accent-soft
|
|
: button-area.pressed ? AppTheme.muted-control-bg
|
|
: button-area.has-hover ? AppTheme.control-bg.brighter(AppTheme.dark ? 8% : 2%)
|
|
: AppTheme.surface;
|
|
private property <color> foreground: root.destructive ? white
|
|
: root.primary ? ThemeUtilities.contrasting-foreground(root.fill-color)
|
|
: root.selected ? AppTheme.accent : AppTheme.heading;
|
|
background: root.fill-color;
|
|
opacity: root.enabled ? 1 : 0.5;
|
|
animate background { duration: 120ms; easing: ease-out; }
|
|
accessible-role: button;
|
|
accessible-label: root.text;
|
|
accessible-action-default => {
|
|
if root.enabled {
|
|
root.clicked();
|
|
}
|
|
}
|
|
|
|
label-row := HorizontalBox {
|
|
y: button-area.pressed ? 1px : 0px;
|
|
animate y { duration: 140ms; easing: spring(0); }
|
|
padding-left: 12px;
|
|
padding-right: 12px;
|
|
spacing: 7px;
|
|
alignment: center;
|
|
cross-axis-alignment: center;
|
|
|
|
if root.has-icon : Image {
|
|
width: root.icon-size;
|
|
height: root.icon-size;
|
|
source: root.icon;
|
|
colorize: root.colorize-icon ? (root.primary || root.destructive ? root.foreground : AppTheme.body) : transparent;
|
|
image-fit: contain;
|
|
accessible-role: none;
|
|
}
|
|
|
|
Text {
|
|
text: root.text;
|
|
color: root.foreground;
|
|
font-size: TypeScale.body;
|
|
font-weight: root.primary || root.destructive || root.selected ? 600 : 500;
|
|
horizontal-alignment: center;
|
|
vertical-alignment: center;
|
|
overflow: root.label-overflow;
|
|
}
|
|
}
|
|
|
|
keyboard := FocusVisibleScope {
|
|
enabled: root.enabled;
|
|
accessible-role: none;
|
|
key-pressed(event) => {
|
|
if event.text == Key.Return || event.text == Key.Space { root.clicked(); return accept; }
|
|
reject
|
|
}
|
|
}
|
|
button-area := TouchArea {
|
|
enabled: root.enabled;
|
|
clicked => { keyboard.focus(); keyboard.pointer-activated(); root.clicked(); }
|
|
mouse-cursor: pointer;
|
|
}
|
|
}
|