mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 22:31:14 +00:00

This cleans up the light and dark mode palette. It reduces the number of duplicate colors and also uses the system default color scheme.
366 lines
11 KiB
Text
366 lines
11 KiB
Text
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
|
// SPDX-License-Identifier: MIT
|
|
import { Palette } from "std-widgets.slint";
|
|
|
|
struct ButtonColors {
|
|
base: color,
|
|
pressed: color,
|
|
hovered: color,
|
|
}
|
|
|
|
struct ModeColors {
|
|
background: color,
|
|
primary: color,
|
|
secondary: color,
|
|
text-primary: color,
|
|
text-secondary: color,
|
|
destructive: color,
|
|
}
|
|
|
|
export global DemoPalette {
|
|
in property <bool> dark-mode: Palette.color-scheme == ColorScheme.dark;
|
|
|
|
property <ModeColors> light-mode-colors: {
|
|
background: #FFFFFF,
|
|
primary: #0E133F,
|
|
secondary: #FFBF63,
|
|
text-primary: #000,
|
|
text-secondary: #6284FF,
|
|
destructive: #FF3B30,
|
|
};
|
|
|
|
property <ModeColors> dark-mode-colors: {
|
|
background: #122F7B,
|
|
primary: #0E133F,
|
|
secondary: #FFBF63,
|
|
text-primary: #F4F6FF,
|
|
text-secondary: #F4F6FF,
|
|
destructive: #FF3B30,
|
|
};
|
|
|
|
out property <color> background: dark-mode ? dark-mode-colors.background : light-mode-colors.background;
|
|
out property <color> primary: dark-mode ? dark-mode-colors.primary : light-mode-colors.primary;
|
|
out property <color> secondary: dark-mode ? dark-mode-colors.secondary : light-mode-colors.secondary;
|
|
out property <color> text-primary: dark-mode ? dark-mode-colors.text-primary : light-mode-colors.text-primary;
|
|
out property <color> text-secondary: dark-mode ? dark-mode-colors.text-secondary : light-mode-colors.text-secondary;
|
|
out property <color> destructive: dark-mode ? dark-mode-colors.destructive : light-mode-colors.destructive;
|
|
|
|
// Fixed (non-themeable) colors
|
|
out property <color> push-button-text-color: white;
|
|
|
|
// Color of the home/settings/ink buttons on the left side bar
|
|
out property <color> active-page-icon-color: root.dark-mode ? #6284FF : #122F7B;
|
|
out property <color> inactive-page-icon-color: #BDC0D1;
|
|
out property <color> neutral-box: #BDC0D1;
|
|
out property <color> secondary-foreground-color: root.dark-mode ? #C1C3CA : #6C6E7A;
|
|
|
|
// Color used for the border / outline of items that can be clicked on, such as the
|
|
// "Print"/"Scan" buttons, the printer queue items (for expansion) or controls such
|
|
// as the combo box or spin box.
|
|
out property <color> control-secondary: #6284FF;
|
|
out property <color> control-foreground: root.dark-mode ? white : #122F7B; // FIXME: the night mode color was not part of the design
|
|
out property <color> primary-push-button-base: #6284FF;
|
|
out property <ButtonColors> primary-push-button-colors: {
|
|
base: root.primary-push-button-base,
|
|
pressed: root.primary-push-button-base.darker(40%),
|
|
hovered: root.primary-push-button-base.darker(20%),
|
|
};
|
|
out property <color> secondary-push-button-base: destructive;
|
|
out property <ButtonColors> secondary-push-button-colors: {
|
|
base: root.secondary-push-button-base,
|
|
pressed: root.secondary-push-button-base.darker(40%),
|
|
hovered: root.secondary-push-button-base.darker(20%),
|
|
};
|
|
|
|
out property <length> base-font-size: 16px;
|
|
out property <length> button-width: 130px;
|
|
out property <length> button-height: button-width + 30px;
|
|
out property <length> side-bar-width: 67px;
|
|
out property <length> side-bar-margin: 10px;
|
|
|
|
}
|
|
|
|
export component Page inherits Rectangle {
|
|
in property <string> header <=> h.text;
|
|
in property <bool> has-back-button: false;
|
|
|
|
callback back;
|
|
|
|
background: DemoPalette.background;
|
|
// Stop accidentally getting clicks dur to animation only moving page half way offscreen
|
|
visible: self.opacity > 0;
|
|
|
|
TouchArea { } // protect underneath controls
|
|
|
|
|
|
|
|
if (root.has-back-button) : Image {
|
|
x:0;
|
|
source: @image-url("images/back.svg");
|
|
image-fit: contain;
|
|
colorize: DemoPalette.control-secondary;
|
|
y: h.y + (h.height - self.height) / 2;
|
|
width: 14px;
|
|
height: 24px;
|
|
|
|
TouchArea {
|
|
clicked => { root.back() }
|
|
|
|
x:0;
|
|
width: 150%;
|
|
}
|
|
}
|
|
|
|
h := Text {
|
|
font-weight: 900;
|
|
font-size: DemoPalette.base-font-size * 2;
|
|
color: DemoPalette.text-primary;
|
|
y: 46px - self.font-size;
|
|
x: root.has-back-button ? 24px + 16px : 0px;
|
|
// Allow clicking on the title as well to get back easier when just
|
|
// using fingers on a small screen.
|
|
if (root.has-back-button) : TouchArea {
|
|
clicked => { root.back() }
|
|
}
|
|
}
|
|
}
|
|
export component Label inherits Text {
|
|
color: DemoPalette.text-primary;
|
|
vertical-alignment: center;
|
|
font-weight: 700;
|
|
vertical-stretch: 0;
|
|
}
|
|
|
|
component SquareButton inherits Rectangle {
|
|
in-out property <image> img;
|
|
|
|
callback clicked;
|
|
|
|
border-radius: 3px;
|
|
border-width: 2px;
|
|
border-color: DemoPalette.secondary;
|
|
|
|
touch := TouchArea {
|
|
clicked => {
|
|
root.clicked();
|
|
}
|
|
}
|
|
|
|
Image {
|
|
height: 40%;
|
|
width: 40%;
|
|
x: (parent.width - self.width)/2;
|
|
y: (parent.height - self.height)/2;
|
|
source <=> root.img;
|
|
image-fit: contain;
|
|
colorize: DemoPalette.control-secondary;
|
|
}
|
|
}
|
|
|
|
export component SpinBox inherits Rectangle {
|
|
in property <int> minimum;
|
|
in property <int> maximum: 100;
|
|
in-out property <int> value;
|
|
|
|
height: 32px;
|
|
|
|
HorizontalLayout {
|
|
spacing: 12px;
|
|
padding: 0;
|
|
|
|
SquareButton {
|
|
clicked => {
|
|
if (root.value > root.minimum) {
|
|
root.value -= 1;
|
|
}
|
|
}
|
|
|
|
width: root.height - parent.padding * 2;
|
|
img: @image-url("images/minus.svg");
|
|
}
|
|
|
|
Rectangle {
|
|
border-radius: 3px;
|
|
border-width: 2px;
|
|
border-color: DemoPalette.secondary;
|
|
|
|
Text {
|
|
width: 100%;
|
|
height: 100%;
|
|
vertical-alignment: center;
|
|
horizontal-alignment: center;
|
|
text: root.value;
|
|
color: DemoPalette.control-foreground;
|
|
}
|
|
}
|
|
|
|
SquareButton {
|
|
clicked => {
|
|
if (root.value < root.maximum) {
|
|
root.value += 1;
|
|
}
|
|
}
|
|
|
|
width: root.height - parent.padding * 2;
|
|
img: @image-url("images/plus.svg");
|
|
}
|
|
}
|
|
}
|
|
|
|
export component ComboBox inherits Rectangle {
|
|
in-out property <string> value;
|
|
in property <[string]> choices;
|
|
callback selected(int);
|
|
|
|
border-radius: 3px;
|
|
border-width: 2px;
|
|
border-color: DemoPalette.secondary;
|
|
height: 32px;
|
|
min-width: label.x + label.width + i.width;
|
|
horizontal-stretch: 1; // Work around #2284
|
|
|
|
label := Text {
|
|
vertical-alignment: center;
|
|
horizontal-alignment: left;
|
|
text <=> root.value;
|
|
color: DemoPalette.control-foreground;
|
|
height: 100%;
|
|
x: 12px;
|
|
}
|
|
|
|
i := Image {
|
|
source: @image-url("images/down.svg");
|
|
colorize: DemoPalette.control-secondary;
|
|
height: 40%;
|
|
width: self.height;
|
|
image-fit: contain;
|
|
x: parent.width - self.width - self.y;
|
|
y: (parent.height - self.height)/2;
|
|
}
|
|
|
|
TouchArea {
|
|
clicked => { popup.show(); }
|
|
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
popup := PopupWindow {
|
|
x:0;
|
|
y: root.height;
|
|
width: root.width;
|
|
|
|
Rectangle {
|
|
background: DemoPalette.background;
|
|
border-radius: 3px;
|
|
border-width: 2px;
|
|
border-color: DemoPalette.secondary;
|
|
}
|
|
|
|
VerticalLayout {
|
|
spacing: 6px;
|
|
padding: 3px;
|
|
function textColor(hashover: bool) -> color {
|
|
if DemoPalette.dark-mode {
|
|
return DemoPalette.text-primary;
|
|
}
|
|
// if hashover {
|
|
return DemoPalette.text-primary;
|
|
// }
|
|
|
|
}
|
|
|
|
for value[idx] in root.choices: Rectangle {
|
|
border-radius: 3px;
|
|
background: item-area.has-hover ? DemoPalette.primary-push-button-colors.hovered : #0000;
|
|
|
|
HorizontalLayout {
|
|
Text {
|
|
text: value;
|
|
color: item-area.has-hover ? DemoPalette.push-button-text-color : DemoPalette.text-primary;
|
|
font-size: DemoPalette.base-font-size;
|
|
}
|
|
}
|
|
|
|
item-area := TouchArea {
|
|
clicked => {
|
|
root.value = value;
|
|
root.selected(idx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export component CheckBox inherits Rectangle {
|
|
in property <string> text;
|
|
in-out property <bool> checked;
|
|
|
|
height: 32px;
|
|
|
|
HorizontalLayout {
|
|
spacing: 12px;
|
|
padding: 0;
|
|
SquareButton {
|
|
clicked => { root.checked = !root.checked; }
|
|
|
|
width: root.height - parent.padding * 2;
|
|
img: root.checked ? @image-url("images/check.svg") : @image-url("");
|
|
}
|
|
|
|
Text {
|
|
text <=> root.text;
|
|
vertical-alignment: center;
|
|
horizontal-alignment: center;
|
|
color: DemoPalette.control-foreground;
|
|
horizontal-stretch: 1;
|
|
}
|
|
}
|
|
|
|
TouchArea {
|
|
clicked => {
|
|
root.checked = !root.checked;
|
|
}
|
|
}
|
|
}
|
|
|
|
export component PushButton inherits Rectangle {
|
|
in property <string> text <=> label.text;
|
|
in property <bool> primary: true;
|
|
out property <bool> pressed: touch-area.pressed;
|
|
out property <ButtonColors> colors: root.primary ? DemoPalette.primary-push-button-colors : DemoPalette.secondary-push-button-colors;
|
|
in-out property <image> icon <=> img.source;
|
|
|
|
callback clicked;
|
|
|
|
border-radius: 13.5px;
|
|
background: root.pressed ? root.colors.pressed : (touch-area.has-hover ? root.colors.hovered : root.colors.base);
|
|
|
|
height: 27px; // line-height in the design
|
|
horizontal-stretch: 1;
|
|
|
|
HorizontalLayout {
|
|
padding-top: 0px;
|
|
padding-bottom: 0px;
|
|
padding-left: parent.border-radius;
|
|
padding-right: parent.border-radius;
|
|
|
|
img := Image {
|
|
horizontal-stretch: 0;
|
|
colorize: DemoPalette.push-button-text-color;
|
|
image-fit: contain;
|
|
width: 17px;
|
|
}
|
|
|
|
label := Text {
|
|
font-weight: 900;
|
|
font-size: DemoPalette.base-font-size * 0.975;
|
|
color: DemoPalette.push-button-text-color;
|
|
horizontal-alignment: center;
|
|
vertical-alignment: center;
|
|
}
|
|
}
|
|
|
|
touch-area := TouchArea { clicked => { root.clicked() } }
|
|
}
|