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