feat(qbz-slint): foundation tokens and login screen
M1 progress. Adds the foundation token layer (palette, semantic colors, spacing, radius, typography) bound to the QBZ dark theme, three primitives (QbzCheckbox, QbzPrimaryButton, QbzTextLink), and the LoginScreen feature component. The login screen mirrors the Svelte LoginView: centered card, logo, QBZ wordmark, Qobuz ToS checkbox, "Sign in via Browser" button, system-browser and offline links, and the legal disclaimer. Colors are lifted verbatim from src/app.css; strings use @tr() markers. Rust side: typed AppCommand enum; UI callbacks dispatch through it. M2 wires the command handler to AppRuntime. cc
This commit is contained in:
15 files changed
+452
-10
No files matched your search
@@ -0,0 +1,33 @@
|
||||
// Small square checkbox primitive matching the QBZ dark theme.
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
|
||||
export component QbzCheckbox inherits Rectangle {
|
||||
in-out property <bool> checked: false;
|
||||
callback toggled();
|
||||
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 4px;
|
||||
background: root.checked ? Theme.accent : transparent;
|
||||
border-width: root.checked ? 0px : 1.5px;
|
||||
border-color: Theme.text-muted;
|
||||
|
||||
Text {
|
||||
text: "✓";
|
||||
visible: root.checked;
|
||||
color: Theme.accent-text;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
horizontal-alignment: center;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
|
||||
TouchArea {
|
||||
mouse-cursor: pointer;
|
||||
clicked => {
|
||||
root.checked = !root.checked;
|
||||
root.toggled();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Full-width accent button primitive.
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Radius } from "../foundation/radius.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
|
||||
export component QbzPrimaryButton inherits Rectangle {
|
||||
in property <string> label;
|
||||
in property <bool> enabled: true;
|
||||
callback clicked();
|
||||
|
||||
height: 48px;
|
||||
border-radius: Radius.sm;
|
||||
opacity: root.enabled ? 1.0 : 0.5;
|
||||
background: ta.has-hover && root.enabled ? Theme.accent-hover : Theme.accent;
|
||||
|
||||
animate background { duration: 150ms; }
|
||||
|
||||
Text {
|
||||
text: root.label;
|
||||
color: Theme.accent-text;
|
||||
font-size: Typography.button;
|
||||
font-weight: Typography.semibold;
|
||||
horizontal-alignment: center;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
|
||||
ta := TouchArea {
|
||||
enabled: root.enabled;
|
||||
mouse-cursor: root.enabled ? pointer : default;
|
||||
clicked => {
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Underlined, muted text-link primitive. Turns accent-colored on hover.
|
||||
|
||||
import { Theme } from "../foundation/semantic-colors.slint";
|
||||
import { Typography } from "../foundation/typography.slint";
|
||||
|
||||
export component QbzTextLink inherits Rectangle {
|
||||
in property <string> label;
|
||||
callback clicked();
|
||||
|
||||
width: txt.preferred-width;
|
||||
height: txt.preferred-height + 3px;
|
||||
|
||||
txt := Text {
|
||||
x: 0;
|
||||
y: 0;
|
||||
text: root.label;
|
||||
color: ta.has-hover ? Theme.accent : Theme.text-muted;
|
||||
font-size: Typography.link;
|
||||
}
|
||||
|
||||
// Underline.
|
||||
Rectangle {
|
||||
x: 0;
|
||||
y: txt.preferred-height + 1px;
|
||||
width: txt.preferred-width;
|
||||
height: 1px;
|
||||
background: ta.has-hover ? Theme.accent : Theme.text-muted;
|
||||
}
|
||||
|
||||
ta := TouchArea {
|
||||
mouse-cursor: pointer;
|
||||
clicked => {
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user