Add native interaction-state animations
This commit is contained in:
1 parent
a291e93608
commit
ad9205fcc9
5 files changed
+60
-9
No files matched your search
@@ -1,4 +1,6 @@
|
||||
use super::*;
|
||||
use gpui::{Animation, AnimationExt, pulsating_between};
|
||||
use std::time::Duration;
|
||||
|
||||
impl AppRoot {
|
||||
pub(super) fn render_inbox(&self) -> impl IntoElement + '_ {
|
||||
@@ -192,7 +194,7 @@ fn inbox_filters(
|
||||
}
|
||||
|
||||
fn filter_chip(label: &'static str, count: usize, active: bool) -> impl IntoElement {
|
||||
div()
|
||||
let chip = div()
|
||||
.px_4()
|
||||
.py_2()
|
||||
.rounded_full()
|
||||
@@ -207,7 +209,19 @@ fn filter_chip(label: &'static str, count: usize, active: bool) -> impl IntoElem
|
||||
} else {
|
||||
theme::text_secondary()
|
||||
})
|
||||
.child(format!("{} {}", label, count))
|
||||
.child(format!("{} {}", label, count));
|
||||
if active {
|
||||
chip.with_animation(
|
||||
("inbox-filter", label.len()),
|
||||
Animation::new(Duration::from_secs(2))
|
||||
.repeat()
|
||||
.with_easing(pulsating_between(0.82, 1.0)),
|
||||
|element, delta| element.opacity(delta),
|
||||
)
|
||||
.into_any_element()
|
||||
} else {
|
||||
chip.into_any_element()
|
||||
}
|
||||
}
|
||||
|
||||
fn inbox_group(label: &'static str, rows: impl Iterator<Item = gpui::Div>) -> impl IntoElement {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use super::*;
|
||||
use gpui::{Animation, AnimationExt, pulsating_between};
|
||||
use std::time::Duration;
|
||||
|
||||
impl AppRoot {
|
||||
pub(super) fn render_onboarding(&self, cx: &mut Context<Self>) -> impl IntoElement + '_ {
|
||||
@@ -151,7 +153,7 @@ fn onboarding_steps() -> impl IntoElement {
|
||||
}
|
||||
|
||||
fn step_chip(label: &'static str, complete: bool) -> impl IntoElement {
|
||||
div()
|
||||
let chip = div()
|
||||
.px_4()
|
||||
.py_2()
|
||||
.rounded_full()
|
||||
@@ -166,7 +168,19 @@ fn step_chip(label: &'static str, complete: bool) -> impl IntoElement {
|
||||
} else {
|
||||
theme::text_secondary()
|
||||
})
|
||||
.child(label)
|
||||
.child(label);
|
||||
if complete {
|
||||
chip.with_animation(
|
||||
("step-chip", label.len()),
|
||||
Animation::new(Duration::from_secs(3))
|
||||
.repeat()
|
||||
.with_easing(pulsating_between(0.78, 1.0)),
|
||||
|element, delta| element.opacity(delta),
|
||||
)
|
||||
.into_any_element()
|
||||
} else {
|
||||
chip.into_any_element()
|
||||
}
|
||||
}
|
||||
|
||||
fn readiness_panel() -> impl IntoElement {
|
||||
@@ -222,7 +236,14 @@ fn success_badge() -> impl IntoElement {
|
||||
.w(px(32.0))
|
||||
.h(px(32.0))
|
||||
.rounded_full()
|
||||
.bg(theme::accent_teal()),
|
||||
.bg(theme::accent_teal())
|
||||
.with_animation(
|
||||
"success-badge-inner",
|
||||
Animation::new(Duration::from_secs(2))
|
||||
.repeat()
|
||||
.with_easing(pulsating_between(0.72, 1.0)),
|
||||
|element, delta| element.opacity(delta),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use super::*;
|
||||
use gpui::{Animation, AnimationExt, pulsating_between};
|
||||
use std::time::Duration;
|
||||
|
||||
impl AppRoot {
|
||||
pub(super) fn render_runs(&self, cx: &mut Context<Self>) -> impl IntoElement + '_ {
|
||||
@@ -319,7 +321,7 @@ fn run_workspace_name(snapshot: &domain::ProfileSnapshot, run: &domain::Run) ->
|
||||
}
|
||||
|
||||
fn run_status_badge(status: &str) -> impl IntoElement {
|
||||
div()
|
||||
let badge = div()
|
||||
.px_3()
|
||||
.py_2()
|
||||
.rounded_full()
|
||||
@@ -334,7 +336,20 @@ fn run_status_badge(status: &str) -> impl IntoElement {
|
||||
"failed" | "timed_out" | "cancelled" | "interrupted" => theme::danger(),
|
||||
_ => theme::text_secondary(),
|
||||
})
|
||||
.child(status.to_uppercase())
|
||||
.child(status.to_uppercase());
|
||||
if status == "running" {
|
||||
badge
|
||||
.with_animation(
|
||||
("run-badge", 1usize),
|
||||
Animation::new(Duration::from_secs(2))
|
||||
.repeat()
|
||||
.with_easing(pulsating_between(0.8, 1.0)),
|
||||
|element, delta| element.opacity(delta),
|
||||
)
|
||||
.into_any_element()
|
||||
} else {
|
||||
badge.into_any_element()
|
||||
}
|
||||
}
|
||||
|
||||
fn info_tile(label: &'static str, value: String) -> impl IntoElement {
|
||||
|
||||
@@ -98,8 +98,8 @@
|
||||
"Verify in native app"
|
||||
],
|
||||
"priority": 7,
|
||||
"passes": false,
|
||||
"notes": "High-value remaining parity layer."
|
||||
"passes": true,
|
||||
"notes": "Completed with GPUI-native animation wrappers on onboarding success states, active inbox filters, and running run status emphasis."
|
||||
},
|
||||
{
|
||||
"id": "US-008",
|
||||
|
||||
@@ -9,3 +9,4 @@ Started: 2026-04-19
|
||||
- Standing constraint: all code is written directly in the current context; no subagents or agent teams are used.
|
||||
- Completed real settings/workspace state mutations in native Rust path: theme, locale, execution mode, and primary workspace.
|
||||
- Added native_settings_workspace_e2e.rs to verify mutation persistence across reopen.
|
||||
- Completed first native motion/state parity layer using GPUI animation wrappers for onboarding, inbox, and runs.
|
||||
Reference in new issue
Block a user