1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4import { CosmicFontSettings, CosmicPalette } from "styling.slint";
5import { StateLayer } from "components.slint";
6
7export component Button {
8 in property <string> text;
9 in property <image> icon;
10 in property <bool> primary;
11 in property <bool> enabled <=> state-layer.enabled;
12 in property <bool> checkable;
13 in property <bool> colorize-icon;
14 out property <bool> has-focus: state-layer.has-focus;
15 out property <bool> pressed: self.enabled && state-layer.pressed;
16 in-out property <bool> checked <=> state-layer.checked;
17
18 callback clicked;
19
20 private property <brush> text-color: primary ? CosmicPalette.accent-foreground : CosmicPalette.control-foreground;
21
22 min-width: max(32px, layout.min-width);
23 min-height: max(32px, layout.min-height);
24 horizontal-stretch: 0;
25 vertical-stretch: 0;
26 forward-focus: state-layer;
27
28 accessible-role: button;
29 accessible-enabled: root.enabled;
30 accessible-checkable: root.checkable;
31 accessible-checked: root.checked;
32 accessible-label: root.text;
33 accessible-action-default => { state-layer.clicked(); }
34
35 states [
36 disabled when !root.enabled : {
37 root.opacity: 0.5;
38 }
39 ]
40
41 background := Rectangle {
42 border-radius: 16px;
43 background: root.primary ? CosmicPalette.accent-background : CosmicPalette.control-background;
44
45 animate background, border-color { duration: 150ms; }
46
47 layout := HorizontalLayout {
48 padding-left: 12px;
49 padding-right: 12px;
50 padding-top: 5px;
51 padding-bottom: 5px;
52 spacing: 4px;
53 alignment: center;
54
55 if (root.icon.width > 0 && root.icon.height > 0) : Image {
56 y: (parent.height - self.height) / 2;
57 source <=> root.icon;
58 width: 20px;
59 colorize: root.colorize-icon ? root.text-color : transparent;
60 }
61
62 if (root.text != ""): Text {
63 font-size: CosmicFontSettings.body.font-size;
64 font-weight: CosmicFontSettings.body.font-weight;
65 horizontal-alignment: center;
66 vertical-alignment: center;
67 text: root.text;
68 color: root.text-color;
69 animate color { duration: 150ms; }
70 accessible-role: none;
71 }
72 }
73 }
74
75 state-layer := StateLayer {
76 border-radius: background.border-radius;
77
78 clicked => {
79 if (root.checkable) {
80 root.checked = !root.checked;
81 }
82 root.clicked();
83 }
84 }
85}
86