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.child.unwrap_or_else(|| div().into_any_element());
65 let kind = self.kind;
66 let animation = Animation::new(Duration::from_millis(self.duration));
67 div()
68 .child(child)
69 .with_animation(self.id, animation, move |el, delta| {
70 let shift = (1.0 - delta) * 8.0;
71 match kind {
72 TransitionKind::Fade => el.opacity(delta),
73 TransitionKind::SlideUp => el.opacity(delta).mt(px(shift)),
74 TransitionKind::SlideDown => el.opacity(delta).mt(px(-shift)),
75 TransitionKind::SlideLeft => el.opacity(delta).ml(px(shift)),
76 TransitionKind::SlideRight => el.opacity(delta).ml(px(-shift)),
77 }
78 })
79 }
80}
81
82#[derive(IntoElement)]
84pub struct Collapse {
85 id: ElementId,
86 open: bool,
87 duration: u64,
88 child: Option<AnyElement>,
89}
90
91impl Collapse {
92 pub fn new(id: impl Into<ElementId>) -> Self {
93 Collapse {
94 id: id.into(),
95 open: false,
96 duration: 180,
97 child: None,
98 }
99 }
100
101 pub fn open(mut self, open: bool) -> Self {
102 self.open = open;
103 self
104 }
105
106 pub fn duration_ms(mut self, duration: u64) -> Self {
107 self.duration = duration;
108 self
109 }
110
111 pub fn child(mut self, child: impl IntoElement) -> Self {
112 self.child = Some(child.into_any_element());
113 self
114 }
115}
116
117impl RenderOnce for Collapse {
118 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
119 if !self.open {
120 return div().into_any_element();
121 }
122 let child = self.child.unwrap_or_else(|| div().into_any_element());
123 let animation = Animation::new(Duration::from_millis(self.duration));
124 div()
125 .child(child)
126 .with_animation(self.id, animation, |el, delta| el.opacity(delta))
127 .into_any_element()
128 }
129}