tailwind_rs_core/utilities/
backgrounds.rs

1//! Background utilities for tailwind-rs
2//!
3//! This module provides utilities for background colors, background images,
4//! background gradients, background positioning, background sizing, and background repeat.
5
6use crate::classes::ClassBuilder;
7use serde::{Deserialize, Serialize};
8use std::fmt;
9
10/// Background attachment values
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub enum BackgroundAttachment {
13    /// Fixed attachment
14    Fixed,
15    /// Local attachment
16    Local,
17    /// Scroll attachment
18    Scroll,
19}
20
21/// Background clip values
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
23pub enum BackgroundClip {
24    /// Border clip
25    Border,
26    /// Padding clip
27    Padding,
28    /// Content clip
29    Content,
30    /// Text clip
31    Text,
32}
33
34/// Background origin values
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
36pub enum BackgroundOrigin {
37    /// Border origin
38    Border,
39    /// Padding origin
40    Padding,
41    /// Content origin
42    Content,
43}
44
45/// Background position values
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
47pub enum BackgroundPosition {
48    /// Bottom position
49    Bottom,
50    /// Center position
51    Center,
52    /// Left position
53    Left,
54    /// Left bottom position
55    LeftBottom,
56    /// Left top position
57    LeftTop,
58    /// Right position
59    Right,
60    /// Right bottom position
61    RightBottom,
62    /// Right top position
63    RightTop,
64    /// Top position
65    Top,
66}
67
68/// Background repeat values
69#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
70pub enum BackgroundRepeat {
71    /// No repeat
72    NoRepeat,
73    /// Repeat
74    Repeat,
75    /// Repeat X
76    RepeatX,
77    /// Repeat Y
78    RepeatY,
79    /// Round repeat
80    Round,
81    /// Space repeat
82    Space,
83}
84
85/// Background size values
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
87pub enum BackgroundSize {
88    /// Auto size
89    Auto,
90    /// Cover size
91    Cover,
92    /// Contain size
93    Contain,
94}
95
96/// Background image values
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
98pub enum BackgroundImage {
99    /// None image
100    None,
101    /// Linear gradient
102    LinearGradient,
103    /// Radial gradient
104    RadialGradient,
105    /// Conic gradient
106    ConicGradient,
107}
108
109/// Gradient direction values
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
111pub enum GradientDirection {
112    /// To right
113    ToRight,
114    /// To left
115    ToLeft,
116    /// To top
117    ToTop,
118    /// To bottom
119    ToBottom,
120    /// To top right
121    ToTopRight,
122    /// To top left
123    ToTopLeft,
124    /// To bottom right
125    ToBottomRight,
126    /// To bottom left
127    ToBottomLeft,
128}
129
130/// Gradient stop values
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
132pub enum GradientStop {
133    /// From stop
134    From,
135    /// Via stop
136    Via,
137    /// To stop
138    To,
139}
140
141impl BackgroundAttachment {
142    pub fn to_class_name(&self) -> String {
143        match self {
144            BackgroundAttachment::Fixed => "fixed".to_string(),
145            BackgroundAttachment::Local => "local".to_string(),
146            BackgroundAttachment::Scroll => "scroll".to_string(),
147        }
148    }
149    
150    pub fn to_css_value(&self) -> String {
151        match self {
152            BackgroundAttachment::Fixed => "fixed".to_string(),
153            BackgroundAttachment::Local => "local".to_string(),
154            BackgroundAttachment::Scroll => "scroll".to_string(),
155        }
156    }
157}
158
159impl BackgroundClip {
160    pub fn to_class_name(&self) -> String {
161        match self {
162            BackgroundClip::Border => "border".to_string(),
163            BackgroundClip::Padding => "padding".to_string(),
164            BackgroundClip::Content => "content".to_string(),
165            BackgroundClip::Text => "text".to_string(),
166        }
167    }
168    
169    pub fn to_css_value(&self) -> String {
170        match self {
171            BackgroundClip::Border => "border-box".to_string(),
172            BackgroundClip::Padding => "padding-box".to_string(),
173            BackgroundClip::Content => "content-box".to_string(),
174            BackgroundClip::Text => "text".to_string(),
175        }
176    }
177}
178
179impl BackgroundOrigin {
180    pub fn to_class_name(&self) -> String {
181        match self {
182            BackgroundOrigin::Border => "border".to_string(),
183            BackgroundOrigin::Padding => "padding".to_string(),
184            BackgroundOrigin::Content => "content".to_string(),
185        }
186    }
187    
188    pub fn to_css_value(&self) -> String {
189        match self {
190            BackgroundOrigin::Border => "border-box".to_string(),
191            BackgroundOrigin::Padding => "padding-box".to_string(),
192            BackgroundOrigin::Content => "content-box".to_string(),
193        }
194    }
195}
196
197impl BackgroundPosition {
198    pub fn to_class_name(&self) -> String {
199        match self {
200            BackgroundPosition::Bottom => "bottom".to_string(),
201            BackgroundPosition::Center => "center".to_string(),
202            BackgroundPosition::Left => "left".to_string(),
203            BackgroundPosition::LeftBottom => "left-bottom".to_string(),
204            BackgroundPosition::LeftTop => "left-top".to_string(),
205            BackgroundPosition::Right => "right".to_string(),
206            BackgroundPosition::RightBottom => "right-bottom".to_string(),
207            BackgroundPosition::RightTop => "right-top".to_string(),
208            BackgroundPosition::Top => "top".to_string(),
209        }
210    }
211    
212    pub fn to_css_value(&self) -> String {
213        match self {
214            BackgroundPosition::Bottom => "bottom".to_string(),
215            BackgroundPosition::Center => "center".to_string(),
216            BackgroundPosition::Left => "left".to_string(),
217            BackgroundPosition::LeftBottom => "left bottom".to_string(),
218            BackgroundPosition::LeftTop => "left top".to_string(),
219            BackgroundPosition::Right => "right".to_string(),
220            BackgroundPosition::RightBottom => "right bottom".to_string(),
221            BackgroundPosition::RightTop => "right top".to_string(),
222            BackgroundPosition::Top => "top".to_string(),
223        }
224    }
225}
226
227impl BackgroundRepeat {
228    pub fn to_class_name(&self) -> String {
229        match self {
230            BackgroundRepeat::NoRepeat => "no-repeat".to_string(),
231            BackgroundRepeat::Repeat => "repeat".to_string(),
232            BackgroundRepeat::RepeatX => "repeat-x".to_string(),
233            BackgroundRepeat::RepeatY => "repeat-y".to_string(),
234            BackgroundRepeat::Round => "round".to_string(),
235            BackgroundRepeat::Space => "space".to_string(),
236        }
237    }
238    
239    pub fn to_css_value(&self) -> String {
240        match self {
241            BackgroundRepeat::NoRepeat => "no-repeat".to_string(),
242            BackgroundRepeat::Repeat => "repeat".to_string(),
243            BackgroundRepeat::RepeatX => "repeat-x".to_string(),
244            BackgroundRepeat::RepeatY => "repeat-y".to_string(),
245            BackgroundRepeat::Round => "round".to_string(),
246            BackgroundRepeat::Space => "space".to_string(),
247        }
248    }
249}
250
251impl BackgroundSize {
252    pub fn to_class_name(&self) -> String {
253        match self {
254            BackgroundSize::Auto => "auto".to_string(),
255            BackgroundSize::Cover => "cover".to_string(),
256            BackgroundSize::Contain => "contain".to_string(),
257        }
258    }
259    
260    pub fn to_css_value(&self) -> String {
261        match self {
262            BackgroundSize::Auto => "auto".to_string(),
263            BackgroundSize::Cover => "cover".to_string(),
264            BackgroundSize::Contain => "contain".to_string(),
265        }
266    }
267}
268
269impl BackgroundImage {
270    pub fn to_class_name(&self) -> String {
271        match self {
272            BackgroundImage::None => "none".to_string(),
273            BackgroundImage::LinearGradient => "gradient-to-r".to_string(),
274            BackgroundImage::RadialGradient => "radial-gradient".to_string(),
275            BackgroundImage::ConicGradient => "conic-gradient".to_string(),
276        }
277    }
278    
279    pub fn to_css_value(&self) -> String {
280        match self {
281            BackgroundImage::None => "none".to_string(),
282            BackgroundImage::LinearGradient => "linear-gradient(to right, var(--tw-gradient-stops))".to_string(),
283            BackgroundImage::RadialGradient => "radial-gradient(ellipse at center, var(--tw-gradient-stops))".to_string(),
284            BackgroundImage::ConicGradient => "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))".to_string(),
285        }
286    }
287}
288
289impl GradientDirection {
290    pub fn to_class_name(&self) -> String {
291        match self {
292            GradientDirection::ToRight => "to-r".to_string(),
293            GradientDirection::ToLeft => "to-l".to_string(),
294            GradientDirection::ToTop => "to-t".to_string(),
295            GradientDirection::ToBottom => "to-b".to_string(),
296            GradientDirection::ToTopRight => "to-tr".to_string(),
297            GradientDirection::ToTopLeft => "to-tl".to_string(),
298            GradientDirection::ToBottomRight => "to-br".to_string(),
299            GradientDirection::ToBottomLeft => "to-bl".to_string(),
300        }
301    }
302    
303    pub fn to_css_value(&self) -> String {
304        match self {
305            GradientDirection::ToRight => "to right".to_string(),
306            GradientDirection::ToLeft => "to left".to_string(),
307            GradientDirection::ToTop => "to top".to_string(),
308            GradientDirection::ToBottom => "to bottom".to_string(),
309            GradientDirection::ToTopRight => "to top right".to_string(),
310            GradientDirection::ToTopLeft => "to top left".to_string(),
311            GradientDirection::ToBottomRight => "to bottom right".to_string(),
312            GradientDirection::ToBottomLeft => "to bottom left".to_string(),
313        }
314    }
315}
316
317impl GradientStop {
318    pub fn to_class_name(&self) -> String {
319        match self {
320            GradientStop::From => "from".to_string(),
321            GradientStop::Via => "via".to_string(),
322            GradientStop::To => "to".to_string(),
323        }
324    }
325    
326    pub fn to_css_value(&self) -> String {
327        match self {
328            GradientStop::From => "from".to_string(),
329            GradientStop::Via => "via".to_string(),
330            GradientStop::To => "to".to_string(),
331        }
332    }
333}
334
335impl fmt::Display for BackgroundAttachment {
336    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
337        write!(f, "{}", self.to_class_name())
338    }
339}
340
341impl fmt::Display for BackgroundClip {
342    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
343        write!(f, "{}", self.to_class_name())
344    }
345}
346
347impl fmt::Display for BackgroundOrigin {
348    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
349        write!(f, "{}", self.to_class_name())
350    }
351}
352
353impl fmt::Display for BackgroundPosition {
354    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355        write!(f, "{}", self.to_class_name())
356    }
357}
358
359impl fmt::Display for BackgroundRepeat {
360    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361        write!(f, "{}", self.to_class_name())
362    }
363}
364
365impl fmt::Display for BackgroundSize {
366    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
367        write!(f, "{}", self.to_class_name())
368    }
369}
370
371impl fmt::Display for BackgroundImage {
372    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
373        write!(f, "{}", self.to_class_name())
374    }
375}
376
377impl fmt::Display for GradientDirection {
378    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379        write!(f, "{}", self.to_class_name())
380    }
381}
382
383impl fmt::Display for GradientStop {
384    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
385        write!(f, "{}", self.to_class_name())
386    }
387}
388
389/// Trait for adding background attachment utilities to a class builder
390pub trait BackgroundAttachmentUtilities {
391    fn background_attachment(self, attachment: BackgroundAttachment) -> Self;
392}
393
394impl BackgroundAttachmentUtilities for ClassBuilder {
395    fn background_attachment(self, attachment: BackgroundAttachment) -> Self {
396        self.class(format!("bg-{}", attachment.to_class_name()))
397    }
398}
399
400/// Trait for adding background clip utilities to a class builder
401pub trait BackgroundClipUtilities {
402    fn background_clip(self, clip: BackgroundClip) -> Self;
403}
404
405impl BackgroundClipUtilities for ClassBuilder {
406    fn background_clip(self, clip: BackgroundClip) -> Self {
407        self.class(format!("bg-clip-{}", clip.to_class_name()))
408    }
409}
410
411/// Trait for adding background origin utilities to a class builder
412pub trait BackgroundOriginUtilities {
413    fn background_origin(self, origin: BackgroundOrigin) -> Self;
414}
415
416impl BackgroundOriginUtilities for ClassBuilder {
417    fn background_origin(self, origin: BackgroundOrigin) -> Self {
418        self.class(format!("bg-origin-{}", origin.to_class_name()))
419    }
420}
421
422/// Trait for adding background position utilities to a class builder
423pub trait BackgroundPositionUtilities {
424    fn background_position(self, position: BackgroundPosition) -> Self;
425}
426
427impl BackgroundPositionUtilities for ClassBuilder {
428    fn background_position(self, position: BackgroundPosition) -> Self {
429        self.class(format!("bg-{}", position.to_class_name()))
430    }
431}
432
433/// Trait for adding background repeat utilities to a class builder
434pub trait BackgroundRepeatUtilities {
435    fn background_repeat(self, repeat: BackgroundRepeat) -> Self;
436}
437
438impl BackgroundRepeatUtilities for ClassBuilder {
439    fn background_repeat(self, repeat: BackgroundRepeat) -> Self {
440        self.class(format!("bg-{}", repeat.to_class_name()))
441    }
442}
443
444/// Trait for adding background size utilities to a class builder
445pub trait BackgroundSizeUtilities {
446    fn background_size(self, size: BackgroundSize) -> Self;
447}
448
449impl BackgroundSizeUtilities for ClassBuilder {
450    fn background_size(self, size: BackgroundSize) -> Self {
451        self.class(format!("bg-{}", size.to_class_name()))
452    }
453}
454
455/// Trait for adding background image utilities to a class builder
456pub trait BackgroundImageUtilities {
457    fn background_image(self, image: BackgroundImage) -> Self;
458}
459
460impl BackgroundImageUtilities for ClassBuilder {
461    fn background_image(self, image: BackgroundImage) -> Self {
462        self.class(format!("bg-{}", image.to_class_name()))
463    }
464}
465
466/// Trait for adding gradient direction utilities to a class builder
467pub trait GradientDirectionUtilities {
468    fn gradient_direction(self, direction: GradientDirection) -> Self;
469}
470
471impl GradientDirectionUtilities for ClassBuilder {
472    fn gradient_direction(self, direction: GradientDirection) -> Self {
473        self.class(format!("bg-gradient-{}", direction.to_class_name()))
474    }
475}
476
477/// Trait for adding gradient stop utilities to a class builder
478pub trait GradientStopUtilities {
479    fn gradient_from(self, color: crate::utilities::colors::Color) -> Self;
480    fn gradient_via(self, color: crate::utilities::colors::Color) -> Self;
481    fn gradient_to(self, color: crate::utilities::colors::Color) -> Self;
482}
483
484impl GradientStopUtilities for ClassBuilder {
485    fn gradient_from(self, color: crate::utilities::colors::Color) -> Self {
486        self.class(format!("from-{}", color.to_class_name()))
487    }
488    
489    fn gradient_via(self, color: crate::utilities::colors::Color) -> Self {
490        self.class(format!("via-{}", color.to_class_name()))
491    }
492    
493    fn gradient_to(self, color: crate::utilities::colors::Color) -> Self {
494        self.class(format!("to-{}", color.to_class_name()))
495    }
496}
497
498#[cfg(test)]
499mod tests {
500    use super::*;
501    use crate::utilities::colors::{Color, ColorPalette, ColorShade};
502    
503    #[test]
504    fn test_background_attachment_utilities() {
505        let classes = ClassBuilder::new()
506            .background_attachment(BackgroundAttachment::Fixed)
507            .background_attachment(BackgroundAttachment::Local)
508            .background_attachment(BackgroundAttachment::Scroll)
509            .build();
510        
511        let css_classes = classes.to_css_classes();
512        assert!(css_classes.contains("bg-fixed"));
513        assert!(css_classes.contains("bg-local"));
514        assert!(css_classes.contains("bg-scroll"));
515    }
516    
517    #[test]
518    fn test_background_clip_utilities() {
519        let classes = ClassBuilder::new()
520            .background_clip(BackgroundClip::Border)
521            .background_clip(BackgroundClip::Padding)
522            .background_clip(BackgroundClip::Content)
523            .background_clip(BackgroundClip::Text)
524            .build();
525        
526        let css_classes = classes.to_css_classes();
527        assert!(css_classes.contains("bg-clip-border"));
528        assert!(css_classes.contains("bg-clip-padding"));
529        assert!(css_classes.contains("bg-clip-content"));
530        assert!(css_classes.contains("bg-clip-text"));
531    }
532    
533    #[test]
534    fn test_background_origin_utilities() {
535        let classes = ClassBuilder::new()
536            .background_origin(BackgroundOrigin::Border)
537            .background_origin(BackgroundOrigin::Padding)
538            .background_origin(BackgroundOrigin::Content)
539            .build();
540        
541        let css_classes = classes.to_css_classes();
542        assert!(css_classes.contains("bg-origin-border"));
543        assert!(css_classes.contains("bg-origin-padding"));
544        assert!(css_classes.contains("bg-origin-content"));
545    }
546    
547    #[test]
548    fn test_background_position_utilities() {
549        let classes = ClassBuilder::new()
550            .background_position(BackgroundPosition::Bottom)
551            .background_position(BackgroundPosition::Center)
552            .background_position(BackgroundPosition::Left)
553            .background_position(BackgroundPosition::Right)
554            .background_position(BackgroundPosition::Top)
555            .build();
556        
557        let css_classes = classes.to_css_classes();
558        assert!(css_classes.contains("bg-bottom"));
559        assert!(css_classes.contains("bg-center"));
560        assert!(css_classes.contains("bg-left"));
561        assert!(css_classes.contains("bg-right"));
562        assert!(css_classes.contains("bg-top"));
563    }
564    
565    #[test]
566    fn test_background_repeat_utilities() {
567        let classes = ClassBuilder::new()
568            .background_repeat(BackgroundRepeat::NoRepeat)
569            .background_repeat(BackgroundRepeat::Repeat)
570            .background_repeat(BackgroundRepeat::RepeatX)
571            .background_repeat(BackgroundRepeat::RepeatY)
572            .background_repeat(BackgroundRepeat::Round)
573            .background_repeat(BackgroundRepeat::Space)
574            .build();
575        
576        let css_classes = classes.to_css_classes();
577        assert!(css_classes.contains("bg-no-repeat"));
578        assert!(css_classes.contains("bg-repeat"));
579        assert!(css_classes.contains("bg-repeat-x"));
580        assert!(css_classes.contains("bg-repeat-y"));
581        assert!(css_classes.contains("bg-round"));
582        assert!(css_classes.contains("bg-space"));
583    }
584    
585    #[test]
586    fn test_background_size_utilities() {
587        let classes = ClassBuilder::new()
588            .background_size(BackgroundSize::Auto)
589            .background_size(BackgroundSize::Cover)
590            .background_size(BackgroundSize::Contain)
591            .build();
592        
593        let css_classes = classes.to_css_classes();
594        assert!(css_classes.contains("bg-auto"));
595        assert!(css_classes.contains("bg-cover"));
596        assert!(css_classes.contains("bg-contain"));
597    }
598    
599    #[test]
600    fn test_background_image_utilities() {
601        let classes = ClassBuilder::new()
602            .background_image(BackgroundImage::None)
603            .background_image(BackgroundImage::LinearGradient)
604            .background_image(BackgroundImage::RadialGradient)
605            .background_image(BackgroundImage::ConicGradient)
606            .build();
607        
608        let css_classes = classes.to_css_classes();
609        assert!(css_classes.contains("bg-none"));
610        assert!(css_classes.contains("bg-gradient-to-r"));
611        assert!(css_classes.contains("bg-radial-gradient"));
612        assert!(css_classes.contains("bg-conic-gradient"));
613    }
614    
615    #[test]
616    fn test_gradient_direction_utilities() {
617        let classes = ClassBuilder::new()
618            .gradient_direction(GradientDirection::ToRight)
619            .gradient_direction(GradientDirection::ToLeft)
620            .gradient_direction(GradientDirection::ToTop)
621            .gradient_direction(GradientDirection::ToBottom)
622            .gradient_direction(GradientDirection::ToTopRight)
623            .gradient_direction(GradientDirection::ToTopLeft)
624            .gradient_direction(GradientDirection::ToBottomRight)
625            .gradient_direction(GradientDirection::ToBottomLeft)
626            .build();
627        
628        let css_classes = classes.to_css_classes();
629        assert!(css_classes.contains("bg-gradient-to-r"));
630        assert!(css_classes.contains("bg-gradient-to-l"));
631        assert!(css_classes.contains("bg-gradient-to-t"));
632        assert!(css_classes.contains("bg-gradient-to-b"));
633        assert!(css_classes.contains("bg-gradient-to-tr"));
634        assert!(css_classes.contains("bg-gradient-to-tl"));
635        assert!(css_classes.contains("bg-gradient-to-br"));
636        assert!(css_classes.contains("bg-gradient-to-bl"));
637    }
638    
639    #[test]
640    fn test_gradient_stop_utilities() {
641        let classes = ClassBuilder::new()
642            .gradient_from(Color::new(ColorPalette::Blue, ColorShade::Shade500))
643            .gradient_via(Color::new(ColorPalette::Purple, ColorShade::Shade500))
644            .gradient_to(Color::new(ColorPalette::Pink, ColorShade::Shade500))
645            .build();
646        
647        let css_classes = classes.to_css_classes();
648        assert!(css_classes.contains("from-blue-500"));
649        assert!(css_classes.contains("via-purple-500"));
650        assert!(css_classes.contains("to-pink-500"));
651    }
652    
653    #[test]
654    fn test_complex_background_combination() {
655        let classes = ClassBuilder::new()
656            .background_attachment(BackgroundAttachment::Fixed)
657            .background_clip(BackgroundClip::Padding)
658            .background_origin(BackgroundOrigin::Border)
659            .background_position(BackgroundPosition::Center)
660            .background_repeat(BackgroundRepeat::NoRepeat)
661            .background_size(BackgroundSize::Cover)
662            .background_image(BackgroundImage::LinearGradient)
663            .gradient_direction(GradientDirection::ToRight)
664            .gradient_from(Color::new(ColorPalette::Blue, ColorShade::Shade500))
665            .gradient_to(Color::new(ColorPalette::Red, ColorShade::Shade500))
666            .build();
667        
668        let css_classes = classes.to_css_classes();
669        assert!(css_classes.contains("bg-fixed"));
670        assert!(css_classes.contains("bg-clip-padding"));
671        assert!(css_classes.contains("bg-origin-border"));
672        assert!(css_classes.contains("bg-center"));
673        assert!(css_classes.contains("bg-no-repeat"));
674        assert!(css_classes.contains("bg-cover"));
675        assert!(css_classes.contains("bg-gradient-to-r"));
676        assert!(css_classes.contains("from-blue-500"));
677        assert!(css_classes.contains("to-red-500"));
678    }
679    
680    /// Test that all Week 8 background utilities are implemented
681    #[test]
682    fn test_week8_background_utilities() {
683        // Test all Week 8 background utilities
684        let classes = ClassBuilder::new()
685            // Background Properties
686            .background_attachment(BackgroundAttachment::Fixed)
687            .background_attachment(BackgroundAttachment::Local)
688            .background_attachment(BackgroundAttachment::Scroll)
689            .background_clip(BackgroundClip::Border)
690            .background_clip(BackgroundClip::Padding)
691            .background_clip(BackgroundClip::Content)
692            .background_clip(BackgroundClip::Text)
693            .background_position(BackgroundPosition::Bottom)
694            .background_position(BackgroundPosition::Center)
695            .background_position(BackgroundPosition::Left)
696            .background_position(BackgroundPosition::Right)
697            .background_position(BackgroundPosition::Top)
698            .background_repeat(BackgroundRepeat::Repeat)
699            .background_repeat(BackgroundRepeat::NoRepeat)
700            .background_repeat(BackgroundRepeat::RepeatX)
701            .background_repeat(BackgroundRepeat::RepeatY)
702            .background_repeat(BackgroundRepeat::Round)
703            .background_repeat(BackgroundRepeat::Space)
704            .background_size(BackgroundSize::Auto)
705            .background_size(BackgroundSize::Cover)
706            .background_size(BackgroundSize::Contain)
707            .build();
708        
709        let css_classes = classes.to_css_classes();
710        
711        // Background Properties
712        assert!(css_classes.contains("bg-fixed"));
713        assert!(css_classes.contains("bg-local"));
714        assert!(css_classes.contains("bg-scroll"));
715        assert!(css_classes.contains("bg-clip-border"));
716        assert!(css_classes.contains("bg-clip-padding"));
717        assert!(css_classes.contains("bg-clip-content"));
718        assert!(css_classes.contains("bg-clip-text"));
719        assert!(css_classes.contains("bg-bottom"));
720        assert!(css_classes.contains("bg-center"));
721        assert!(css_classes.contains("bg-left"));
722        assert!(css_classes.contains("bg-right"));
723        assert!(css_classes.contains("bg-top"));
724        assert!(css_classes.contains("bg-repeat"));
725        assert!(css_classes.contains("bg-no-repeat"));
726        assert!(css_classes.contains("bg-repeat-x"));
727        assert!(css_classes.contains("bg-repeat-y"));
728        assert!(css_classes.contains("bg-round"));
729        assert!(css_classes.contains("bg-space"));
730        assert!(css_classes.contains("bg-auto"));
731        assert!(css_classes.contains("bg-cover"));
732        assert!(css_classes.contains("bg-contain"));
733    }
734}