Breadlock UI update: motion system, depth polish, and new animations

Adds a full motion system to the lock screen (staggered entrance, dot pop
+ caret, wrong-password shake, success flash, clock crossfade), depth
polish (gradient veil, pill shadow + hairline border, "Enter password"
hint, responsive typography), and a second wave of animations (idle
breathing, success dot cascade, status slide-in, parallax unlock drift,
animated checking ellipsis, opt-in Ken Burns wallpaper pan). Includes a
dev-only breadlock-preview harness that renders every state to PNGs with
no Wayland involved, and a design/sketch.html prototype.

Fixes text alpha being dropped by cosmic-text's glyph-mask path (all text
fades now work) and double-drifting that made the date/status overlap the
clock/pill during unlock.
This commit is contained in:
Breadway 2026-08-21 12:28:41 +08:00
parent 647a211a93
commit f0b66cd791
14 changed files with 1771 additions and 84 deletions

View file

@ -26,6 +26,10 @@ pub struct Background {
/// v2 feature flag — no-op (with a warning) in v1, which only supports a
/// static color or image background.
pub blur: bool,
/// Slow Ken Burns pan on image backgrounds (a gentle drift + zoom instead
/// of a static image). CPU cost: the background redraws continuously at a
/// low frame rate while locked, so this is opt-in.
pub ken_burns: bool,
}
impl Default for Background {
@ -34,6 +38,7 @@ impl Default for Background {
mode: BackgroundMode::Color,
path: String::new(),
blur: false,
ken_burns: false,
}
}
}
@ -42,12 +47,16 @@ impl Default for Background {
#[serde(default)]
pub struct Clock {
pub format: String,
/// strftime format for the date line under the clock. Empty string hides
/// the date. `%A` = full weekday, `%b` = abbreviated month, `%d` = day.
pub date_format: String,
}
impl Default for Clock {
fn default() -> Self {
Self {
format: "%H:%M".to_string(),
date_format: "%A · %b %d".to_string(),
}
}
}
@ -89,7 +98,9 @@ mod tests {
fn defaults_match_design_system() {
let a = Appearance::default();
assert_eq!(a.background.mode, BackgroundMode::Color);
assert!(!a.background.ken_burns, "Ken Burns must be opt-in (CPU cost)");
assert_eq!(a.clock.format, "%H:%M");
assert_eq!(a.clock.date_format, "%A · %b %d");
assert_eq!(a.font.family, "Varela Round");
}