1use std::time::Duration;
13
14use gpui::prelude::*;
15use gpui::{div, px, Animation, AnimationExt, AnyElement, App, ElementId, IntoElement, Window};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum TransitionKind {
20 Fade,
21 SlideUp,
22 SlideDown,
23 SlideLeft,
24 SlideRight,
25}
26
27#[derive(IntoElement)]
29pub struct Transition {
30 id: ElementId,
31 kind: TransitionKind,
32 duration: u64,
33 child: Option<AnyElement>,
34}
35
36impl Transition {
37 pub fn new(id: impl Into<ElementId>) -> Self {
38 Transition {
39 id: id.into(),
40 kind: TransitionKind::Fade,
41 duration: 200,
42 child: None,
43 }
44 }
45
46 pub fn kind(mut self, kind: TransitionKind) -> Self {
47 self.kind = kind;
48 self
49 }
50
51 pub fn duration_ms(mut self, duration: u64) -> Self {
52 self.duration = duration;
53 self
54 }
55
56 pub fn child(mut self, child: impl IntoElement) -> Self {
57 self.child = Some(child.into_any_element());
58 self
59 }
60}
61
62impl RenderOnce for Transition {
63 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
64 let child = self
65 .child
66 .unwrap_or_else(|| div().into_any_element());
67 let kind = self.kind;
68 let animation = Animation::new(Duration::from_millis(self.duration));
69 div()
70 .child(child)
71 .with_animation(self.id, animation, move |el, delta| {
72 let shift = (1.0 - delta) * 8.0;
73 match kind {
74 TransitionKind::Fade => el.opacity(delta),
75 TransitionKind::SlideUp => el.opacity(delta).mt(px(shift)),
76 TransitionKind::SlideDown => el.opacity(delta).mt(px(-shift)),
77 TransitionKind::SlideLeft => el.opacity(delta).ml(px(shift)),
78 TransitionKind::SlideRight => el.opacity(delta).ml(px(-shift)),
79 }
80 })
81 }
82}
83
84#[derive(IntoElement)]
86pub struct Collapse {
87 id: ElementId,
88 open: bool,
89 duration: u64,
90 child: Option<AnyElement>,
91}
92
93impl Collapse {
94 pub fn new(id: impl Into<ElementId>) -> Self {
95 Collapse {
96 id: id.into(),
97 open: false,
98 duration: 180,
99 child: None,
100 }
101 }
102
103 pub fn open(mut self, open: bool) -> Self {
104 self.open = open;
105 self
106 }
107
108 pub fn duration_ms(mut self, duration: u64) -> Self {
109 self.duration = duration;
110 self
111 }
112
113 pub fn child(mut self, child: impl IntoElement) -> Self {
114 self.child = Some(child.into_any_element());
115 self
116 }
117}
118
119impl RenderOnce for Collapse {
120 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
121 if !self.open {
122 return div().into_any_element();
123 }
124 let child = self
125 .child
126 .unwrap_or_else(|| div().into_any_element());
127 let animation = Animation::new(Duration::from_millis(self.duration));
128 div()
129 .child(child)
130 .with_animation(self.id, animation, |el, delta| el.opacity(delta))
131 .into_any_element()
132 }
133}