Skip to repository content276 lines · 10.9 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T04:44:41.003Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
animation.rs
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