Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T04:44:41.003Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

animation.rs

276 lines · 10.9 KB · rust
1use crate::prelude::*;
2use gpui::{AnimationElement, AnimationExt, Styled};
3use std::time::Duration;
4
5use gpui::ease_out_quint;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum AnimationDuration {
9    Instant = 50,
10    Fast = 150,
11    Slow = 300,
12}
13
14impl AnimationDuration {
15    pub fn duration(&self) -> Duration {
16        Duration::from_millis(*self as u64)
17    }
18}
19
20impl Into<std::time::Duration> for AnimationDuration {
21    fn into(self) -> Duration {
22        self.duration()
23    }
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
27pub enum AnimationDirection {
28    FromBottom,
29    FromLeft,
30    FromRight,
31    FromTop,
32}
33
34pub trait DefaultAnimations: Styled + Sized + Element {
35    fn animate_in(
36        self,
37        animation_type: AnimationDirection,
38        fade_in: bool,
39    ) -> AnimationElement<Self> {
40        let animation_name = match animation_type {
41            AnimationDirection::FromBottom => "animate_from_bottom",
42            AnimationDirection::FromLeft => "animate_from_left",
43            AnimationDirection::FromRight => "animate_from_right",
44            AnimationDirection::FromTop => "animate_from_top",
45        };
46
47        let animation_id = self.id().map_or_else(
48            || ElementId::from(animation_name),
49            |id| (id, animation_name).into(),
50        );
51
52        self.with_animation(
53            animation_id,
54            gpui::Animation::new(AnimationDuration::Fast.into()).with_easing(ease_out_quint()),
55            move |mut this, delta| {
56                let start_opacity = 0.4;
57                let start_pos = 0.0;
58                let end_pos = 40.0;
59
60                if fade_in {
61                    this = this.opacity(start_opacity + delta * (1.0 - start_opacity));
62                }
63
64                match animation_type {
65                    AnimationDirection::FromBottom => {
66                        this.bottom(px(start_pos + delta * (end_pos - start_pos)))
67                    }
68                    AnimationDirection::FromLeft => {
69                        this.left(px(start_pos + delta * (end_pos - start_pos)))
70                    }
71                    AnimationDirection::FromRight => {
72                        this.right(px(start_pos + delta * (end_pos - start_pos)))
73                    }
74                    AnimationDirection::FromTop => {
75                        this.top(px(start_pos + delta * (end_pos - start_pos)))
76                    }
77                }
78            },
79        )
80    }
81
82    fn animate_in_from_bottom(self, fade: bool) -> AnimationElement<Self> {
83        self.animate_in(AnimationDirection::FromBottom, fade)
84    }
85
86    fn animate_in_from_left(self, fade: bool) -> AnimationElement<Self> {
87        self.animate_in(AnimationDirection::FromLeft, fade)
88    }
89
90    fn animate_in_from_right(self, fade: bool) -> AnimationElement<Self> {
91        self.animate_in(AnimationDirection::FromRight, fade)
92    }
93
94    fn animate_in_from_top(self, fade: bool) -> AnimationElement<Self> {
95        self.animate_in(AnimationDirection::FromTop, fade)
96    }
97}
98
99impl<E: Styled + Element> DefaultAnimations for E {}
100
101// Don't use this directly, it only exists to show animation previews
102#[derive(RegisterComponent)]
103struct Animation {}
104
105impl Component for Animation {
106    fn scope() -> ComponentScope {
107        ComponentScope::Utilities
108    }
109
110    fn description() -> &'static str {
111        "Demonstrates various animation patterns and transitions available in the UI system."
112    }
113
114    fn preview(_window: &mut Window, cx: &mut App) -> AnyElement {
115        let container_size = 128.0;
116        let element_size = 32.0;
117        let offset = container_size / 2.0 - element_size / 2.0;
118
119        let container = || {
120            h_flex()
121                .relative()
122                .justify_center()
123                .bg(cx.theme().colors().text.opacity(0.05))
124                .border_1()
125                .border_color(cx.theme().colors().border)
126                .rounded_sm()
127        };
128
129        v_flex()
130            .gap_6()
131            .children(vec![
132                example_group_with_title(
133                    "Animate In",
134                    vec![
135                        single_example(
136                            "From Bottom",
137                            container()
138                                .size(px(container_size))
139                                .child(
140                                    div()
141                                        .id("animate-in-from-bottom")
142                                        .absolute()
143                                        .size(px(element_size))
144                                        .left(px(offset))
145                                        .rounded_md()
146                                        .bg(gpui::red())
147                                        .animate_in_from_bottom(false),
148                                )
149                                .into_any_element(),
150                        ),
151                        single_example(
152                            "From Top",
153                            container()
154                                .size(px(container_size))
155                                .child(
156                                    div()
157                                        .id("animate-in-from-top")
158                                        .absolute()
159                                        .size(px(element_size))
160                                        .left(px(offset))
161                                        .rounded_md()
162                                        .bg(gpui::blue())
163                                        .animate_in_from_top(false),
164                                )
165                                .into_any_element(),
166                        ),
167                        single_example(
168                            "From Left",
169                            container()
170                                .size(px(container_size))
171                                .child(
172                                    div()
173                                        .id("animate-in-from-left")
174                                        .absolute()
175                                        .size(px(element_size))
176                                        .top(px(offset))
177                                        .rounded_md()
178                                        .bg(gpui::green())
179                                        .animate_in_from_left(false),
180                                )
181                                .into_any_element(),
182                        ),
183                        single_example(
184                            "From Right",
185                            container()
186                                .size(px(container_size))
187                                .child(
188                                    div()
189                                        .id("animate-in-from-right")
190                                        .absolute()
191                                        .size(px(element_size))
192                                        .top(px(offset))
193                                        .rounded_md()
194                                        .bg(gpui::yellow())
195                                        .animate_in_from_right(false),
196                                )
197                                .into_any_element(),
198                        ),
199                    ],
200                )
201                .grow(),
202                example_group_with_title(
203                    "Fade and Animate In",
204                    vec![
205                        single_example(
206                            "From Bottom",
207                            container()
208                                .size(px(container_size))
209                                .child(
210                                    div()
211                                        .id("fade-animate-in-from-bottom")
212                                        .absolute()
213                                        .size(px(element_size))
214                                        .left(px(offset))
215                                        .rounded_md()
216                                        .bg(gpui::red())
217                                        .animate_in_from_bottom(true),
218                                )
219                                .into_any_element(),
220                        ),
221                        single_example(
222                            "From Top",
223                            container()
224                                .size(px(container_size))
225                                .child(
226                                    div()
227                                        .id("fade-animate-in-from-top")
228                                        .absolute()
229                                        .size(px(element_size))
230                                        .left(px(offset))
231                                        .rounded_md()
232                                        .bg(gpui::blue())
233                                        .animate_in_from_top(true),
234                                )
235                                .into_any_element(),
236                        ),
237                        single_example(
238                            "From Left",
239                            container()
240                                .size(px(container_size))
241                                .child(
242                                    div()
243                                        .id("fade-animate-in-from-left")
244                                        .absolute()
245                                        .size(px(element_size))
246                                        .top(px(offset))
247                                        .rounded_md()
248                                        .bg(gpui::green())
249                                        .animate_in_from_left(true),
250                                )
251                                .into_any_element(),
252                        ),
253                        single_example(
254                            "From Right",
255                            container()
256                                .size(px(container_size))
257                                .child(
258                                    div()
259                                        .id("fade-animate-in-from-right")
260                                        .absolute()
261                                        .size(px(element_size))
262                                        .top(px(offset))
263                                        .rounded_md()
264                                        .bg(gpui::yellow())
265                                        .animate_in_from_right(true),
266                                )
267                                .into_any_element(),
268                        ),
269                    ],
270                )
271                .grow(),
272            ])
273            .into_any_element()
274    }
275}
276
Served at tenant.openagents/omega Member data and write actions are omitted.