tailwind_rs_core/responsive/
mod.rs

1//! # Responsive Design System Module
2//!
3//! This module provides a comprehensive responsive design system for tailwind-rs.
4//! It's organized into focused sub-modules for better maintainability:
5//! - `breakpoints` - Breakpoint definitions and utilities
6//! - `states` - State definitions for pseudo-classes
7//! - `responsive_values` - Responsive value handling
8//! - `responsive_config` - Configuration management
9//! - `responsive_builder` - Builder pattern for responsive classes
10//! - `flexbox` - Flexbox-specific responsive utilities
11//! - `grid` - Grid-specific responsive utilities
12
13pub mod breakpoints;
14pub mod flexbox;
15pub mod grid;
16pub mod responsive_builder;
17pub mod responsive_config;
18pub mod responsive_values;
19pub mod states;
20
21// Re-export main types for backward compatibility
22pub use breakpoints::Breakpoint;
23pub use flexbox::{AlignItems, FlexDirection, FlexWrap, JustifyContent, ResponsiveFlex};
24pub use grid::ResponsiveGrid;
25pub use responsive_builder::ResponsiveBuilder;
26pub use responsive_config::{Responsive, ResponsiveConfig};
27pub use responsive_values::ResponsiveValue;
28pub use states::State;
29
30/// Create a new responsive configuration with default settings
31pub fn create_responsive_config() -> ResponsiveConfig {
32    ResponsiveConfig::default()
33}
34
35/// Create a new responsive builder
36pub fn create_responsive_builder() -> ResponsiveBuilder {
37    ResponsiveBuilder::default()
38}
39
40/// Create a new responsive flex container
41pub fn create_responsive_flex() -> ResponsiveFlex {
42    ResponsiveFlex::default()
43}
44
45/// Create a new responsive grid container
46pub fn create_responsive_grid() -> ResponsiveGrid {
47    ResponsiveGrid::default()
48}
49
50/// Utility functions for responsive design
51pub mod utils {
52    use super::*;
53
54    /// Check if a breakpoint is active based on screen width
55    pub fn is_breakpoint_active(breakpoint: Breakpoint, screen_width: u32) -> bool {
56        screen_width >= breakpoint.min_width()
57    }
58
59    /// Get the appropriate breakpoint for a given screen width
60    pub fn get_breakpoint_for_width(screen_width: u32) -> Breakpoint {
61        if screen_width >= Breakpoint::Xl2.min_width() {
62            Breakpoint::Xl2
63        } else if screen_width >= Breakpoint::Xl.min_width() {
64            Breakpoint::Xl
65        } else if screen_width >= Breakpoint::Lg.min_width() {
66            Breakpoint::Lg
67        } else if screen_width >= Breakpoint::Md.min_width() {
68            Breakpoint::Md
69        } else if screen_width >= Breakpoint::Sm.min_width() {
70            Breakpoint::Sm
71        } else {
72            Breakpoint::Base
73        }
74    }
75
76    /// Generate responsive classes for a given breakpoint
77    pub fn generate_responsive_classes<T: ToString>(
78        base: T,
79        sm: Option<T>,
80        md: Option<T>,
81        lg: Option<T>,
82        xl: Option<T>,
83        xl2: Option<T>,
84    ) -> String {
85        let mut classes = Vec::new();
86
87        classes.push(base.to_string());
88
89        if let Some(sm_val) = sm {
90            classes.push(format!("sm:{}", sm_val.to_string()));
91        }
92        if let Some(md_val) = md {
93            classes.push(format!("md:{}", md_val.to_string()));
94        }
95        if let Some(lg_val) = lg {
96            classes.push(format!("lg:{}", lg_val.to_string()));
97        }
98        if let Some(xl_val) = xl {
99            classes.push(format!("xl:{}", xl_val.to_string()));
100        }
101        if let Some(xl2_val) = xl2 {
102            classes.push(format!("2xl:{}", xl2_val.to_string()));
103        }
104
105        classes.join(" ")
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112
113    #[test]
114    fn test_create_responsive_config() {
115        let config = create_responsive_config();
116        assert_eq!(config.breakpoints.len(), 6); // Base, Sm, Md, Lg, Xl, Xl2
117    }
118
119    #[test]
120    fn test_create_responsive_builder() {
121        let builder = create_responsive_builder();
122        assert!(builder.is_empty());
123    }
124
125    #[test]
126    fn test_create_responsive_flex() {
127        let flex = create_responsive_flex();
128        assert_eq!(
129            flex.direction.get_breakpoint(Breakpoint::Base),
130            Some(&FlexDirection::Row)
131        );
132    }
133
134    #[test]
135    fn test_create_responsive_grid() {
136        let grid = create_responsive_grid();
137        assert_eq!(grid.columns.get(&Breakpoint::Base), Some(&1));
138    }
139
140    #[test]
141    fn test_is_breakpoint_active() {
142        assert!(utils::is_breakpoint_active(Breakpoint::Base, 0));
143        assert!(utils::is_breakpoint_active(Breakpoint::Sm, 640));
144        assert!(utils::is_breakpoint_active(Breakpoint::Md, 768));
145        assert!(!utils::is_breakpoint_active(Breakpoint::Sm, 639));
146    }
147
148    #[test]
149    fn test_get_breakpoint_for_width() {
150        assert_eq!(utils::get_breakpoint_for_width(0), Breakpoint::Base);
151        assert_eq!(utils::get_breakpoint_for_width(640), Breakpoint::Sm);
152        assert_eq!(utils::get_breakpoint_for_width(768), Breakpoint::Md);
153        assert_eq!(utils::get_breakpoint_for_width(1024), Breakpoint::Lg);
154        assert_eq!(utils::get_breakpoint_for_width(1280), Breakpoint::Xl);
155        assert_eq!(utils::get_breakpoint_for_width(1536), Breakpoint::Xl2);
156    }
157
158    #[test]
159    fn test_generate_responsive_classes() {
160        let classes = utils::generate_responsive_classes(
161            "text-sm",
162            Some("text-base"),
163            Some("text-lg"),
164            Some("text-xl"),
165            None,
166            None,
167        );
168
169        assert!(classes.contains("text-sm"));
170        assert!(classes.contains("sm:text-base"));
171        assert!(classes.contains("md:text-lg"));
172        assert!(classes.contains("lg:text-xl"));
173        assert!(!classes.contains("xl:"));
174        assert!(!classes.contains("2xl:"));
175    }
176}