diff --git a/icons/cog.svg b/icons/cog.svg
new file mode 100644
index 0000000..493377c
--- /dev/null
+++ b/icons/cog.svg
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/logos/external_link.svg b/icons/external_link.svg
similarity index 100%
rename from logos/external_link.svg
rename to icons/external_link.svg
diff --git a/logos/globe.svg b/icons/globe.svg
similarity index 100%
rename from logos/globe.svg
rename to icons/globe.svg
diff --git a/icons/moon.svg b/icons/moon.svg
new file mode 100644
index 0000000..af08447
--- /dev/null
+++ b/icons/moon.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/icons/sun.svg b/icons/sun.svg
new file mode 100644
index 0000000..0809dad
--- /dev/null
+++ b/icons/sun.svg
@@ -0,0 +1,12 @@
+
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 1fe84a1..cc0483d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -63,10 +63,6 @@ fn init() -> State {
println!("Settings clicked");
});
- main_window.on_feedback_clicked(move || {
- println!("Feedback clicked");
- });
-
main_window.on_open_clicked(move || {
println!("Open clicked");
});
diff --git a/ui/button.slint b/ui/button.slint
new file mode 100644
index 0000000..472b10c
--- /dev/null
+++ b/ui/button.slint
@@ -0,0 +1,35 @@
+import { Theme } from "theme.slint";
+
+export component GradientButton inherits Rectangle {
+ callback clicked <=> touch.clicked;
+ in property text;
+
+ background: Theme.gradient-main;
+ border-radius: Theme.radius;
+ drop-shadow-offset-x: Theme.shadow-primary-x;
+ drop-shadow-offset-y: Theme.shadow-primary-y;
+ drop-shadow-blur: Theme.shadow-primary-blur;
+ drop-shadow-color: touch.has-hover ? Theme.shadow-color : transparent;
+ horizontal-stretch: 0;
+
+ animate drop-shadow-color { duration: 300ms; }
+
+ touch := TouchArea {
+ mouse-cursor: pointer;
+ }
+
+ HorizontalLayout {
+ padding: Theme.spacing-sm;
+ padding-left: Theme.spacing-xl;
+ padding-right: Theme.spacing-xl;
+
+ Text {
+ text: text;
+ font-family: "Segoe UI";
+ font-size: 14px;
+ font-weight: 600;
+ min-width: self.preferred-width;
+ min-height: self.preferred-height;
+ }
+ }
+}
diff --git a/ui/footer.slint b/ui/footer.slint
index 8c23b50..d2e61a3 100644
--- a/ui/footer.slint
+++ b/ui/footer.slint
@@ -1,37 +1,66 @@
-import {
- Button,
- HorizontalBox,
- VerticalBox,
-} from "std-widgets.slint";
+import { IconButton } from "icon_button.slint";
+import { Theme } from "theme.slint";
+import { GradientButton } from "button.slint";
export component Footer inherits Rectangle {
callback settings-clicked();
- callback feedback-clicked();
callback open-clicked();
- HorizontalBox {
- spacing: 16px;
- padding-top: 16px;
+ property cog_icon: @image-url("../icons/cog.svg");
+ property sun_icon: @image-url("../icons/sun.svg");
+ property moon_icon: @image-url("../icons/moon.svg");
- HorizontalBox {
+ width: 448px;
+
+ Rectangle {
+ height: 1px;
+ width: 100%;
+ y: 0px;
+ background: Theme.border-main;
+ }
+
+ HorizontalLayout {
+ alignment: space-between;
+ spacing: Theme.spacing-lg;
+ padding: Theme.spacing-md;
+ padding-left: Theme.spacing-lg;
+
+ HorizontalLayout {
spacing: 16px;
- Button {
- text: "⚙️ Настроить";
- clicked => {
- root.settings-clicked();
+ VerticalLayout {
+ alignment: center;
+ IconButton {
+ icon: sun_icon;
+ clicked => {
+ Theme.toggle();
+ }
}
}
- Button {
- text: "💬 Обратная связь";
- clicked => {
- root.feedback-clicked();
+ VerticalLayout {
+ alignment: center;
+ IconButton {
+ icon: cog_icon;
+ clicked => {
+ root.settings-clicked();
+ }
}
}
}
- Button {
+ HorizontalLayout {
+ alignment: center;
+ VerticalLayout {
+ alignment: center;
+ Text {
+ text: "Escape - закрыть";
+ color: Theme.text-hint;
+ }
+ }
+ }
+
+ GradientButton {
text: "Открыть";
clicked => {
root.open-clicked();
diff --git a/ui/header.slint b/ui/header.slint
index 9aed392..1eb5641 100644
--- a/ui/header.slint
+++ b/ui/header.slint
@@ -1,40 +1,38 @@
import { BrowserConfig } from "./types.slint";
-
+import { Theme } from "theme.slint";
export component Header inherits Rectangle {
in property url;
- property icon-gradient: @linear-gradient(135deg, rgb(59, 130, 246), rgb(6, 182, 212));
VerticalLayout {
- // width: 100%;
- width: 448px;
- padding: 12px;
- padding-top: 20px;
- spacing: 12px;
+ width: 100%;
+ padding: Theme.spacing-md;
+ padding-top: Theme.spacing-xl;
+ spacing: Theme.spacing-md;
HorizontalLayout {
- spacing: 12px;
+ spacing: Theme.spacing-md;
Rectangle {
width: 48px;
height: 48px;
- border-radius: 12px;
- background: icon-gradient;
+ border-radius: Theme.radius;
+ background: Theme.gradient-main;
Image {
- source: @image-url("../logos/globe.svg");
+ source: @image-url("../icons/globe.svg");
colorize: white;
}
}
VerticalLayout {
alignment: center;
- spacing: 4px;
+ spacing: Theme.spacing-xs;
Text {
font-family: "Segpoe UI";
text: "Выберите браузер";
- color: #ffffff;
+ color: Theme.text-main;
font-size: 18px;
font-weight: 600;
}
@@ -42,7 +40,7 @@ export component Header inherits Rectangle {
Text {
font-family: "Segpoe UI";
text: "Для открытия ссылки";
- color: #94a3b8;
+ color: Theme.text-muted;
font-size: 14px;
}
}
@@ -50,22 +48,22 @@ export component Header inherits Rectangle {
Rectangle {
height: 44px;
- border-radius: 12px;
- background: #1e293b;
+ border-radius: Theme.radius;
+ background: Theme.surface-elevated;
border-width: 1px;
- border-color: #334155;
+ border-color: Theme.border-main;
HorizontalLayout {
- padding: 12px;
- padding-left: 16px;
- padding-right: 16px;
- spacing: 8px;
+ padding: Theme.spacing-md;
+ padding-left: Theme.spacing-lg;
+ padding-right: Theme.spacing-lg;
+ spacing: Theme.spacing-sm;
alignment: start;
Image {
- source: @image-url("../logos/external_link.svg");
+ source: @image-url("../icons/external_link.svg");
width: 16px;
- colorize: #64748b;
+ colorize: Theme.text-control-muted;
height: 16px;
}
@@ -74,7 +72,7 @@ export component Header inherits Rectangle {
Text {
text: "ku6epxboctuk.github.io";
- color: #cbd5e1;
+ color: Theme.text-control;
font-size: 14px;
font-family: "Consolas";
}
@@ -87,6 +85,6 @@ export component Header inherits Rectangle {
height: 1px;
width: 100%;
y: parent.height - self.height;
- background: #334155;
+ background: Theme.border-main;
}
}
diff --git a/ui/icon_button.slint b/ui/icon_button.slint
new file mode 100644
index 0000000..461c300
--- /dev/null
+++ b/ui/icon_button.slint
@@ -0,0 +1,19 @@
+export component IconButton inherits Rectangle {
+ callback clicked <=> touch.clicked;
+
+ in property icon;
+ property icon_color: touch.has-hover ? #ffffff : #94a3b8;
+ height: 24px;
+ width: 24px;
+ background: transparent;
+ touch := TouchArea {
+ mouse-cursor: pointer;
+ }
+
+ Image {
+ source: icon;
+ colorize: icon_color;
+ width: 24px;
+ height: 24px;
+ }
+}
diff --git a/ui/main.slint b/ui/main.slint
index 1d1e34c..a93bc11 100644
--- a/ui/main.slint
+++ b/ui/main.slint
@@ -3,6 +3,7 @@ import { BrowserItem } from "./browser_item.slint";
import { Header } from "./header.slint";
import { Footer } from "./footer.slint";
import { BrowserConfig } from "./types.slint";
+import { Theme } from "theme.slint";
export component MainWindow inherits Window {
in property <[BrowserConfig]> browser-model: [];
@@ -15,7 +16,6 @@ export component MainWindow inherits Window {
callback toggle-remember(bool);
callback toggle-always-ask(bool);
callback settings-clicked();
- callback feedback-clicked();
callback open-clicked();
callback request-drag();
@@ -30,20 +30,19 @@ export component MainWindow inherits Window {
width: 488px;
height: 800px;
- padding: 20px;
+ padding: Theme.spacing-xl;
Rectangle {
max-width: 448px;
width: 100%;
height: 760px;
- border-radius: 16px;
+ border-radius: Theme.radius-lg;
clip: true;
- background: #0f172a;
+ background: Theme.surface-main;
border-width: 1px;
- border-color: #334155;
+ border-color: Theme.border-main;
VerticalLayout {
- padding: 12px;
Header {
url: current-url;
@@ -83,9 +82,8 @@ export component MainWindow inherits Window {
}
Footer {
- settings-clicked => settings-clicked();
- feedback-clicked => feedback-clicked();
- open-clicked => open-clicked();
+ settings-clicked => root.settings-clicked();
+ open-clicked => root.open-clicked();
}
}
}
diff --git a/ui/theme.slint b/ui/theme.slint
new file mode 100644
index 0000000..51efa4b
--- /dev/null
+++ b/ui/theme.slint
@@ -0,0 +1,42 @@
+export global Theme {
+ in-out property is-dark: true;
+
+ out property width: 448px;
+
+ out property surface-main: is-dark ? #0f172a : #ffffff;
+ out property surface-control: is-dark ? #1e293b4d : #ffffff;
+ out property surface-elevated: is-dark ? #1e293b80 : #ffffff;
+ out property surface-hover: is-dark ? #1e293b : #ffffff;
+
+ out property border-main: is-dark ? #334155 : #ffffff;
+
+ out property gradient-main: @linear-gradient(135deg, rgb(59, 130, 246), rgb(6, 182, 212));
+
+ out property text-main: is-dark ? #ffffff : #000000;
+ out property text-muted: is-dark ? #94a3b8 : #000000;
+
+ out property text-control: is-dark ? #cbd5e1 : #000000;
+ out property text-control-muted: is-dark ? #64748b : #000000;
+
+ out property text-hint: is-dark ? #475569 : #000000;
+
+ out property shadow-color: is-dark ? #3b82f640 : #000000;
+
+ out property shadow-primary-x: 0px;
+ out property shadow-primary-y: 10px;
+ out property shadow-primary-blur: 15px;
+
+ out property radius: 12px;
+ out property radius-lg: 16px;
+
+ out property spacing-xl: 20px;
+ out property spacing-lg: 16px;
+ out property spacing-md: 12px;
+ out property spacing-sm: 8px;
+ out property spacing-xs: 4px;
+
+ callback toggle();
+ toggle => {
+ is-dark = !is-dark;
+ }
+}