1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: MIT
3
4import { Theme } from "../theme.slint";
5
6component Tab {
7 in property <string> title;
8 in property <bool> selected;
9 in property <image> icon;
10
11 callback clicked <=> i-touch-area.clicked;
12
13 private property <angle> angle: Math.atan(self.height / 2 / self.width);
14 private property <bool> has-icon: root.icon.width > 0 && root.icon.height > 0;
15
16 preferred-width: 200px;
17
18 states [
19 selected when selected : {
20 i-initiator.width: root.width;
21 i-title.color: Theme.palette.lemon-green;
22 i-gradient.opacity: 1.0;
23 }
24 ]
25
26 GridLayout {
27 padding: root.has-icon ? 7px : 25px;
28
29 VerticalLayout {
30 spacing: root.has-icon ? 7px : 0;
31
32 if (root.has-icon) : Image {
33 x: (parent.width - self.width) / 2;
34 width: 24px;
35 height: 24px;
36 source: root.icon;
37 colorize: i-title.color;
38 }
39
40 i-title := Text {
41 text: title;
42 horizontal-alignment: center;
43 vertical-alignment: center;
44 font-size: root.has-icon ? Theme.typo.description-light.size : Theme.typo.header-item-light.size;
45 font-weight: root.has-icon ? Theme.typo.header-item-light.weight : Theme.typo.description-light.weight;
46 color: Theme.palette.white;
47
48 animate color { duration: Theme.durations.medium; }
49 }
50 }
51 }
52
53 i-gradient := Rectangle {
54 opacity: 0;
55 visible: !root.has-icon;
56
57 Rectangle {
58 y: 0;
59 width: 50%;
60 height: 50%;
61 x: 0;
62 background: @linear-gradient(angle, rgba(222, 251, 58, 0) , rgba(222, 251, 58, 0.2));
63 }
64
65 Rectangle {
66 y: 0;
67 width: 50%;
68 height: 50%;
69 x: self.width;
70 background: @linear-gradient(-angle, rgba(222, 251, 58, 0) , rgba(222, 251, 58, 0.2));
71 }
72
73 animate opacity { duration: Theme.durations.medium; }
74 }
75
76 i-initiator := Rectangle {
77 width: 0;
78 y: 0;
79 height: 1px;
80 background: Theme.palette.lemon-green;
81 visible: selected;
82
83 animate width { duration: Theme.durations.medium; }
84 }
85
86 i-touch-area := TouchArea {}
87}
88
89export struct TabItem {
90 text: string,
91 icon: image
92}
93
94export component TabWidget {
95 in property <[TabItem]> tabs;
96 in-out property <int> selected-tab;
97
98 vertical-stretch: 1;
99
100 VerticalLayout {
101 Rectangle {
102 vertical-stretch: 1;
103
104 @children
105 }
106
107 Rectangle {
108 vertical-stretch: 0;
109 background: Theme.palette.tab-gradient;
110
111 HorizontalLayout {
112 alignment: center;
113 min-height: 80px;
114 vertical-stretch: 0;
115
116 for tab[index] in tabs : Tab {
117 title: tab.text;
118 icon: tab.icon;
119 selected: index == selected-tab;
120
121 clicked => {
122 selected-tab = index;
123 }
124 }
125 }
126 }
127 }
128}
129