T10b feedback: error views with 404, 403, maintenance and offline, error boundary, drawn results, confirmation card, saving, sync and connection lines, countdown and timer with rolling digits

This commit is contained in:
ZacharyZhang-NY committed 2026-09-25 16:19:41 -04:00
1 parent f895424a08
commit 866335912a
24 files changed
+1806 -173

No files matched your search

+34 -29
View File
@@ -1,8 +1,8 @@
use std::time::{Duration, Instant};
use gpui::{
Animation, AnimationExt, App, ElementId, IntoElement, ParentElement, RenderOnce, Styled, Task,
Window, div, prelude::*,
Animation, AnimationExt, AnyElement, App, ElementId, IntoElement, ParentElement, RenderOnce,
Styled, Task, Window, div, prelude::*,
};
use crate::{
@@ -31,6 +31,33 @@ struct Seen {
_hide: Option<Task<()>>,
}
/// The state's dot, in its color; it breathes while reconnecting.
pub(crate) fn connectivity_dot(
id: impl Into<ElementId>,
state: Connectivity,
cx: &App,
) -> AnyElement {
let theme = cx.theme();
let colors = &theme.colors;
let tone = match state {
Connectivity::Online => colors.success,
Connectivity::Reconnecting => colors.warning,
Connectivity::Offline => colors.fg_subtle,
};
let dot = div().size(theme.status_dot()).rounded_full().bg(tone);
if state != Connectivity::Reconnecting || theme.reduced_motion {
return dot.into_any_element();
}
dot.with_animation(
id,
Animation::new(motion::duration(motion::SLOW, cx) * 3)
.repeat()
.with_easing(motion::ease_in_out_cubic),
|dot, t| dot.opacity(0.35 + 0.65 * (1.0 - (2.0 * t - 1.0).abs())),
)
.into_any_element()
}
/// A quiet pill while offline or reconnecting, and briefly once back.
#[derive(IntoElement)]
pub struct OfflineIndicator {
@@ -77,14 +104,10 @@ impl RenderOnce for OfflineIndicator {
let (back_at, generation) = (seen.read(cx).back_at, seen.read(cx).generation);
let theme = cx.theme();
let colors = &theme.colors;
let (icon, dot, label) = match state {
Connectivity::Offline => (
IconName::WifiOff,
colors.fg_subtle,
"Offline · changes stay on this device",
),
Connectivity::Reconnecting => (IconName::Wifi, colors.warning, "Reconnecting…"),
Connectivity::Online => (IconName::Wifi, colors.success, "Back online"),
let (icon, label) = match state {
Connectivity::Offline => (IconName::WifiOff, "Offline · changes stay on this device"),
Connectivity::Reconnecting => (IconName::Wifi, "Reconnecting…"),
Connectivity::Online => (IconName::Wifi, "Back online"),
};
let showing =
state != Connectivity::Online || back_at.is_some_and(|at| at.elapsed() < HOLD);
@@ -107,25 +130,7 @@ impl RenderOnce for OfflineIndicator {
.shadow(theme.elevation(crate::theme::Elevation::Raised))
.text_size(theme.text_size(TextSize::Sm))
.text_color(colors.fg_muted)
.child({
let light = div()
.size(theme.icon_size(IconSize::Xs) / 2.0)
.rounded_full()
.bg(dot);
if state == Connectivity::Reconnecting && !still {
light
.with_animation(
"reconnect-pulse",
Animation::new(motion::duration(motion::SLOW, cx) * 3)
.repeat()
.with_easing(motion::ease_in_out_cubic),
|dot, t| dot.opacity(0.35 + 0.65 * (1.0 - (2.0 * t - 1.0).abs())),
)
.into_any_element()
} else {
light.into_any_element()
}
})
.child(connectivity_dot("dot", state, cx))
.child(Icon::new(icon).size(IconSize::Sm).color(colors.fg_muted))
.child(label)
.with_animation(