tailwind_rs_yew/
lib.rs

1//! # Tailwind-rs Yew Integration
2//!
3//! This crate provides seamless integration between Tailwind CSS and the Yew framework.
4//! It follows our TDD-first approach (ADR-001) and comprehensive testing pyramid strategy (ADR-002).
5//!
6//! ## Features
7//!
8//! - **Type-safe class generation** - Compile-time validation of Tailwind classes
9//! - **Component-based styling** - Yew component integration with Tailwind
10//! - **Performance optimized** - Efficient class caching and tree-shaking
11//! - **Framework integration** - Native Yew component support
12//!
13//! ## Quick Start
14//!
15//! ```rust
16//! use yew::prelude::*;
17//! use tailwind_rs_yew::{Button, ButtonProps, ButtonVariant};
18//!
19//! #[function_component]
20//! pub fn MyButton(props: &ButtonProps) -> Html {
21//!     let classes = yew::classes! {
22//!         "px-4", "py-2", "rounded-md", "font-medium", "transition-colors",
23//!         match props.variant {
24//!             ButtonVariant::Primary => "bg-blue-600",
25//!             ButtonVariant::Secondary => "bg-gray-200",
26//!             ButtonVariant::Danger => "bg-red-600",
27//!             ButtonVariant::Outline => "border border-gray-300",
28//!         },
29//!     };
30//!     
31//!     html! {
32//!         <button class={classes}>
33//!             {props.children.clone()}
34//!         </button>
35//!     }
36//! }
37//! ```
38
39pub mod class_generator;
40pub mod components;
41pub mod props;
42pub mod utils;
43
44pub use class_generator::*;
45pub use components::*;
46pub use props::*;
47pub use utils::*;
48
49// Re-export core functionality
50pub use tailwind_rs_core::*;
51pub use tailwind_rs_macros::*;
52
53/// Yew-specific class generation utilities
54pub mod yew_classes {
55    use tailwind_rs_core::ClassBuilder;
56    use yew::prelude::*;
57
58    /// Create classes for Yew components
59    pub fn create_yew_classes(builder: ClassBuilder) -> Classes {
60        Classes::from(builder.build().to_css_classes())
61    }
62
63    /// Create conditional classes for Yew components
64    pub fn create_conditional_classes(
65        base_classes: &str,
66        condition: bool,
67        conditional_classes: &str,
68    ) -> Classes {
69        let classes = if condition {
70            format!("{} {}", base_classes, conditional_classes)
71        } else {
72            base_classes.to_string()
73        };
74        Classes::from(classes)
75    }
76
77    /// Create responsive classes for Yew components
78    pub fn create_responsive_classes(
79        base_classes: &str,
80        responsive: &[(crate::Breakpoint, &str)],
81    ) -> Classes {
82        let mut result = base_classes.to_string();
83
84        for (breakpoint, classes) in responsive {
85            result.push(' ');
86            result.push_str(&format!("{}{}", breakpoint.prefix(), classes));
87        }
88
89        Classes::from(result)
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96
97    #[test]
98    fn test_yew_class_generation() {
99        let builder = ClassBuilder::new()
100            .class("px-4 py-2")
101            .class("bg-blue-600 text-white");
102
103        let classes = yew_classes::create_yew_classes(builder);
104        let class_string = classes.to_string();
105
106        assert!(class_string.contains("px-4"));
107        assert!(class_string.contains("bg-blue-600"));
108    }
109
110    #[test]
111    fn test_conditional_class_generation() {
112        let classes = yew_classes::create_conditional_classes("px-4", true, "bg-blue-600");
113
114        let class_string = classes.to_string();
115        assert!(class_string.contains("px-4"));
116        assert!(class_string.contains("bg-blue-600"));
117
118        let classes = yew_classes::create_conditional_classes("px-4", false, "bg-blue-600");
119
120        let class_string = classes.to_string();
121        assert!(class_string.contains("px-4"));
122        assert!(!class_string.contains("bg-blue-600"));
123    }
124
125    #[test]
126    fn test_responsive_class_generation() {
127        let responsive = vec![(Breakpoint::Sm, "text-sm"), (Breakpoint::Md, "text-base")];
128
129        let classes = yew_classes::create_responsive_classes("px-4", &responsive);
130        let class_string = classes.to_string();
131
132        assert!(class_string.contains("sm:text-sm"));
133        assert!(class_string.contains("md:text-base"));
134    }
135}