Skip to main content

gpui_component/theme/
motion.rs

1use std::time::Duration;
2
3use gpui::{Rems, rems};
4use gpui_base::{Easing, Spring};
5
6/// Semantic motion policy shared by styled components.
7#[derive(Clone, Debug)]
8pub struct MotionTokens {
9    pub duration_instant: Duration,
10    pub duration_fast: Duration,
11    pub duration_normal: Duration,
12    pub duration_slow: Duration,
13    pub easing_enter: Easing,
14    pub easing_exit: Easing,
15    pub easing_move: Easing,
16    pub spring_control: Spring,
17    pub spring_move: Spring,
18    pub distance_short: Rems,
19    pub distance_medium: Rems,
20}
21
22impl Default for MotionTokens {
23    fn default() -> Self {
24        Self {
25            duration_instant: Duration::ZERO,
26            duration_fast: Duration::from_millis(120),
27            duration_normal: Duration::from_millis(180),
28            duration_slow: Duration::from_millis(280),
29            easing_enter: Easing::cubic_bezier(0.16, 1.0, 0.3, 1.0)
30                .expect("static enter curve is valid"),
31            easing_exit: Easing::cubic_bezier(0.4, 0.0, 1.0, 1.0)
32                .expect("static exit curve is valid"),
33            easing_move: Easing::cubic_bezier(0.2, 0.0, 0.0, 1.0)
34                .expect("static move curve is valid"),
35            spring_control: Spring::new(Duration::from_millis(180)),
36            spring_move: Spring::new(Duration::from_millis(280))
37                .with_damping(0.85)
38                .with_epsilon(0.1),
39            distance_short: rems(0.25),
40            distance_medium: rems(0.5),
41        }
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn normalized_and_pixel_springs_use_unit_appropriate_tolerances() {
51        let motion = MotionTokens::default();
52
53        assert!(motion.spring_control.epsilon() < 0.01);
54        assert_eq!(motion.spring_move.epsilon(), 0.1);
55    }
56}