1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: MIT
3
4global Utils {
5 public pure function MapRange(value: length, inMin: length, inMax: length, outMin: length, outMax: length) -> length {
6 return clamp(outMin, (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin, outMax);
7 }
8}
9component SunMoonThumb {
10 in property <float> scale: 1;
11 in property <length> thumb-position: 50px * scale;
12
13
14 Rectangle {
15 width: 200px * scale;
16 height: 100px * scale;
17 border-radius: self.height / 2;
18 clip: true;
19 Rectangle {
20 width: 0px;
21 height: 0px;
22 x: root.thumb-position;
23 Rectangle {
24 width: 260px * scale;
25 height: self.width;
26 background: white;
27 border-radius: self.width / 2;
28 opacity: 0.05;
29 }
30 Rectangle {
31 width: 200px * scale;
32 height: self.width;
33 background: white;
34 border-radius: self.width / 2;
35 opacity: 0.05;
36 }
37 Rectangle {
38 width: 140px * scale;
39 height: self.width;
40 background: white;
41 border-radius: self.width / 2;
42 opacity: 0.05;
43 }
44
45 clipper :=Rectangle {
46 width: 85px * scale;
47 height: self.width;
48 border-radius: self.width / 2;
49 clip: true;
50
51 sun := Rectangle {
52 width: 85px * scale;
53 height: self.width;
54 background: @radial-gradient(circle,#ffce08 0%, #fdd224 80%, #fce37f 100%);
55 border-radius: self.width / 2;
56 }
57
58 moon := Rectangle {
59 x: Utils.MapRange(root.thumb-position, 50px * scale, 100px * scale, 85px * scale, 0px);
60 width: 85px * scale;
61 height: self.width;
62 background: @radial-gradient(circle,#bcbcbc 0%, #e7e7e7 80%, #ffffff 100%);
63 border-radius: self.width / 2;
64 }
65 }
66 }
67 }
68}
69
70
71
72enum Theme { day, night }
73export component SunMoonSwitch {
74 property <Theme> theme: Theme.night;
75 in property <float> scale: 1;
76 width: 200px * scale;
77 height: 100px * scale;
78
79 frameBacker := Rectangle {
80 width: parent.width;
81 height: parent.height;
82 background: #1e2232;
83 border-radius: self.height / 2;
84 }
85
86
87 Rectangle {
88 width: parent.width;
89 height: parent.height;
90 clip: true;
91 border-radius: self.height / 2;
92
93 clouds-background :=Image {
94 x: 14px * scale;
95 y: -6px * scale;
96 width: 202px * scale;
97 source: @image-url("images/clouds-background.png");
98 }
99 clouds-foreground := Image {
100 x: 30px * scale;
101 y: 5px * scale;
102 width: 202px * scale;
103 source: @image-url("images/clouds-front.png");
104 }
105
106 stars := Image {
107 x: 15px * scale;
108 y: 15px * scale;
109 width: 80px * scale;
110 source: @image-url("images/stars.png");
111 }
112 }
113
114
115
116 Image {
117 x: -1px * scale;
118 width: 202px * scale;
119 source: @image-url("images/shadow-frame.png");
120 }
121
122 thumb := SunMoonThumb {
123 scale: root.scale;
124 }
125
126 TouchArea {
127 clicked => {
128 if root.theme == Theme.day {
129 root.theme = Theme.night;
130 } else {
131 root.theme = Theme.day;
132 }
133 }
134 }
135
136 states [
137 nightMode when root.theme == Theme.night: {
138 thumb.thumb-position: root.width - thumb.width - 50px * scale;
139 frameBacker.background: #1e2232;
140 clouds-background.y: 120px;
141 clouds-foreground.y: 120px;
142 in {
143 animate frameBacker.background, stars.y, stars.opacity {
144 easing: ease-out-sine;
145 duration: 200ms;
146 }
147 animate thumb.thumb-position {
148 easing: cubic-bezier(0.61, 0.21, 0.68, 1.22);
149 duration: 300ms;
150 }
151 animate clouds-background.y, clouds-foreground.y {
152 easing: ease-in-sine;
153 duration: 150ms;
154 }
155 }
156 }
157 dayMode when root.theme == Theme.day: {
158 thumb.thumb-position: 50px * scale;
159 frameBacker.background: #3d85ba;
160 stars.y: - 60px * scale;
161 stars.opacity: 0.4;
162 in {
163 animate frameBacker.background, stars.y, stars.opacity {
164 easing: ease-out-sine;
165 duration: 200ms;
166 }
167 animate thumb.thumb-position {
168 easing: cubic-bezier(0.61, 0.21, 0.68, 1.22);
169 duration: 300ms;
170 }
171 animate clouds-background.y {
172 easing: ease-out-sine;
173 duration: 300ms;
174 }
175 animate clouds-foreground.y {
176 easing: cubic-bezier(0.61, 0.21, 0.68, 1.22);
177 duration: 350ms;
178 }
179 }
180 }
181 ]
182}
183