slint/demos/home-automation/ui/components/general/themeSwitch.slint
2024-10-25 15:55:03 +02:00

186 lines
5.7 KiB
Text

// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: MIT
import { Palette } from "../../common.slint";
import { Palette as StdPalette } from "std-widgets.slint";
global Utils {
public pure function MapRange(value: length, inMin: length, inMax: length, outMin: length, outMax: length) -> length {
return clamp(outMin, (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin, outMax);
}
}
component SunMoonThumb {
in property <float> scale: 1;
in property <length> thumb-position: 50px;
Rectangle {
width: 200px * scale;
height: 100px * scale;
border-radius: self.height / 2;
clip: true;
Rectangle {
width: 0px;
height: 0px;
x: root.thumb-position;
Rectangle {
width: 260px * scale;
height: self.width;
background: white;
border-radius: self.width / 2;
opacity: 0.05;
}
Rectangle {
width: 200px * scale;
height: self.width;
background: white;
border-radius: self.width / 2;
opacity: 0.05;
}
Rectangle {
x: 0;
width: 140px * scale;
height: self.width;
background: white;
border-radius: self.width / 2;
opacity: 0.05;
}
clipper := Rectangle {
width: 85px * scale;
height: self.width;
border-radius: self.width / 2;
clip: true;
sun := Rectangle {
width: 85px * scale;
height: self.width;
background: @radial-gradient(circle, #ffce08 0%, #fdd224 80%, #fce37f 100%);
border-radius: self.width / 2;
}
moon := Rectangle {
x: Utils.MapRange(root.thumb-position, 50px * scale, 100px * scale, 85px * scale, 0px);
width: 85px * scale;
height: self.width;
background: @radial-gradient(circle, #bcbcbc 0%, #e7e7e7 80%, #ffffff 100%);
border-radius: self.width / 2;
}
}
}
}
}
enum Theme { day, night }
export component ThemeSwitch {
in property <float> scale: 1;
width: 200px * scale;
height: 100px * scale;
property <Theme> theme: Theme.night;
frameBacker := Rectangle {
width: parent.width;
height: parent.height;
background: #1e2232;
border-radius: self.height / 2;
}
Rectangle {
width: parent.width;
height: parent.height;
clip: true;
border-radius: self.height / 2;
clouds-background := Image {
x: 14px * scale;
y: -6px * scale;
width: 202px * scale;
source: @image-url("../../images/clouds-background.png");
}
clouds-foreground := Image {
x: 30px * scale;
y: 5px * scale;
width: 202px * scale;
source: @image-url("../../images/clouds-front.png");
}
stars := Image {
x: 15px * scale;
y: 15px * scale;
width: 80px * scale;
source: @image-url("../../images/stars.png");
}
}
Rectangle {
border-radius: self.height / 2;
border-color: #474747;
border-width: 1phx;
}
thumb := SunMoonThumb {
scale: root.scale;
}
TouchArea {
clicked => {
if root.theme == Theme.day {
root.theme = Theme.night;
Palette.dark-color-scheme = true;
StdPalette.color-scheme = ColorScheme.dark;
} else {
root.theme = Theme.day;
Palette.dark-color-scheme = false;
StdPalette.color-scheme = ColorScheme.light;
}
}
}
states [
nightMode when root.theme == Theme.night: {
thumb.thumb-position: root.width - thumb.width - (50px * scale);
frameBacker.background: #1e2232;
clouds-background.y: 120px;
clouds-foreground.y: 120px;
in {
animate frameBacker.background, stars.y, stars.opacity {
easing: ease-out-sine;
duration: 200ms;
}
animate thumb.thumb-position {
easing: cubic-bezier(0.61, 0.21, 0.68, 1.22);
duration: 300ms;
}
animate clouds-background.y, clouds-foreground.y {
easing: ease-in-sine;
duration: 150ms;
}
}
}
dayMode when root.theme == Theme.day: {
thumb.thumb-position: 50px * scale;
frameBacker.background: #3d85ba;
stars.y: - 60px;
stars.opacity: 0.4;
in {
animate frameBacker.background, stars.y, stars.opacity {
easing: ease-out-sine;
duration: 200ms;
}
animate thumb.thumb-position {
easing: cubic-bezier(0.61, 0.21, 0.68, 1.22);
duration: 300ms;
}
animate clouds-background.y {
easing: ease-out-sine;
duration: 300ms;
}
animate clouds-foreground.y {
easing: cubic-bezier(0.61, 0.21, 0.68, 1.22);
duration: 350ms;
}
}
}
]
}