Skip to main content

use_motion_preference/
lib.rs

1#![forbid(unsafe_code)]
2//! Primitive reduced-motion preference helpers.
3//!
4//! These helpers keep policy decisions explicit and deterministic.
5//!
6//! # Examples
7//!
8//! ```rust
9//! use use_motion_preference::{
10//!     AnimationPolicy, MotionPreference, adjust_duration_ms, animation_policy,
11//!     should_disable_animation, should_reduce_motion,
12//! };
13//!
14//! assert_eq!(
15//!     animation_policy(MotionPreference::Reduce, false),
16//!     AnimationPolicy::Disable
17//! );
18//! assert_eq!(
19//!     animation_policy(MotionPreference::Reduce, true),
20//!     AnimationPolicy::Reduce
21//! );
22//! assert!(should_reduce_motion(MotionPreference::Reduce));
23//! assert!(should_disable_animation(MotionPreference::Reduce, false));
24//! assert_eq!(adjust_duration_ms(400, MotionPreference::Reduce), 200);
25//! ```
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum MotionPreference {
29    NoPreference,
30    Reduce,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub enum AnimationPolicy {
35    Allow,
36    Reduce,
37    Disable,
38}
39
40#[must_use]
41pub fn animation_policy(preference: MotionPreference, essential: bool) -> AnimationPolicy {
42    match (preference, essential) {
43        (MotionPreference::NoPreference, _) => AnimationPolicy::Allow,
44        (MotionPreference::Reduce, true) => AnimationPolicy::Reduce,
45        (MotionPreference::Reduce, false) => AnimationPolicy::Disable,
46    }
47}
48
49#[must_use]
50pub fn should_reduce_motion(preference: MotionPreference) -> bool {
51    preference == MotionPreference::Reduce
52}
53
54#[must_use]
55pub fn should_disable_animation(preference: MotionPreference, essential: bool) -> bool {
56    animation_policy(preference, essential) == AnimationPolicy::Disable
57}
58
59#[must_use]
60pub fn adjust_duration_ms(duration_ms: u64, preference: MotionPreference) -> u64 {
61    match preference {
62        MotionPreference::NoPreference => duration_ms,
63        MotionPreference::Reduce if duration_ms == 0 => 0,
64        MotionPreference::Reduce => (duration_ms / 2).max(1),
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::{
71        AnimationPolicy, MotionPreference, adjust_duration_ms, animation_policy,
72        should_disable_animation, should_reduce_motion,
73    };
74
75    #[test]
76    fn applies_reduced_motion_policy_behavior() {
77        assert_eq!(
78            animation_policy(MotionPreference::NoPreference, false),
79            AnimationPolicy::Allow
80        );
81        assert_eq!(
82            animation_policy(MotionPreference::Reduce, true),
83            AnimationPolicy::Reduce
84        );
85        assert_eq!(
86            animation_policy(MotionPreference::Reduce, false),
87            AnimationPolicy::Disable
88        );
89        assert!(should_reduce_motion(MotionPreference::Reduce));
90        assert!(should_disable_animation(MotionPreference::Reduce, false));
91        assert_eq!(adjust_duration_ms(400, MotionPreference::Reduce), 200);
92        assert_eq!(adjust_duration_ms(1, MotionPreference::Reduce), 1);
93    }
94}