mew_css/properties.rs
1//! # CSS Properties Module
2//!
3//! This module defines the CSS properties that can be set on a style. It provides
4//! a structured way to create and manage CSS properties with type safety.
5//!
6//! ## Module Organization
7//!
8//! The properties are organized into submodules by category:
9//!
10//! - `color`: Color-related properties (color, background-color)
11//! - `size`: Size-related properties (width, height, margin, padding)
12//! - `display`: Display and positioning properties
13//! - `font`: Typography-related properties
14//! - `border`: Border and outline properties
15//! - `position`: Positioning properties (top, right, bottom, left)
16//! - `layout`: General layout properties (overflow, visibility)
17//! - `flex`: Flexbox-specific properties
18//! - `grid`: Grid-specific properties
19//! - `transition`: Transition and animation properties
20//!
21//! ## Usage
22//!
23//! While you can use this module directly to create properties, it's generally
24//! easier to use the methods on the `Style` struct, which will call these
25//! functions for you.
26//!
27//! ```rust
28//! use mew_css::properties::{Property, color};
29//! use mew_css::values::Color;
30//!
31//! // Direct usage
32//! let property = color::color(Color::Blue);
33//!
34//! // More commonly, through the Style API
35//! use mew_css::style;
36//! let css = style().color(Color::Blue).apply();
37//! ```
38
39use crate::values::*;
40use std::fmt;
41
42/// Represents a single CSS property with a name and value.
43///
44/// A `Property` is the fundamental building block of CSS styles in this library.
45/// Each property has a name (like "color" or "margin-top") and a value that has
46/// been converted to a string representation.
47///
48/// Properties are typically created using the functions in the submodules of this
49/// module, rather than being constructed directly.
50///
51/// # Examples
52///
53/// ```rust
54/// use mew_css::properties::Property;
55///
56/// // Create a property directly
57/// let color_prop = Property::new("color", "blue");
58/// let font_size_prop = Property::new("font-size", "16px");
59///
60/// // The string representation includes the semicolon
61/// assert_eq!(color_prop.to_string(), "color: blue;");
62/// ```
63#[derive(Debug, Clone)]
64pub struct Property {
65 /// The CSS property name (e.g., "color", "margin-top")
66 name: String,
67 /// The CSS property value as a string (e.g., "blue", "20px")
68 value: String,
69}
70
71impl Property {
72 /// Creates a new CSS property with the given name and value.
73 ///
74 /// This method converts the value to a string using the `Display` trait.
75 ///
76 /// # Arguments
77 ///
78 /// * `name` - The CSS property name
79 /// * `value` - The property value, which can be any type that implements `Display`
80 ///
81 /// # Returns
82 ///
83 /// A new `Property` instance
84 ///
85 /// # Examples
86 ///
87 /// ```rust
88 /// use mew_css::properties::Property;
89 ///
90 /// let color_prop = Property::new("color", "blue");
91 /// let margin_prop = Property::new("margin", "10px");
92 /// let opacity_prop = Property::new("opacity", 0.5);
93 /// ```
94 pub fn new<T: fmt::Display>(name: &str, value: T) -> Self {
95 Self {
96 name: name.to_string(),
97 value: value.to_string(),
98 }
99 }
100}
101
102impl fmt::Display for Property {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 write!(f, "{}: {};", self.name, self.value)
105 }
106}
107
108/// Color-related CSS properties.
109///
110/// This module provides functions for creating color-related CSS properties
111/// such as text color, background color, and border color.
112pub mod color {
113 use super::*;
114
115 /// Creates a CSS `color` property for setting text color.
116 ///
117 /// The `color` property sets the color of text content and text decorations.
118 ///
119 /// # Arguments
120 ///
121 /// * `value` - The color value to use
122 ///
123 /// # Returns
124 ///
125 /// A new `Property` instance representing the color property
126 ///
127 /// # Examples
128 ///
129 /// ```rust
130 /// use mew_css::properties::color;
131 /// use mew_css::values::Color;
132 ///
133 /// let prop = color::color(Color::Blue);
134 /// assert_eq!(prop.to_string(), "color: blue;");
135 ///
136 /// let prop = color::color(Color::Rgb(255, 0, 0));
137 /// assert_eq!(prop.to_string(), "color: rgb(255, 0, 0);");
138 /// ```
139 pub fn color(value: Color) -> Property {
140 Property::new("color", value)
141 }
142
143 /// Creates a CSS `background-color` property for setting element background color.
144 ///
145 /// The `background-color` property sets the background color of an element.
146 /// The background covers the element's content, padding, and border areas.
147 ///
148 /// # Arguments
149 ///
150 /// * `value` - The color value to use
151 ///
152 /// # Returns
153 ///
154 /// A new `Property` instance representing the background-color property
155 ///
156 /// # Examples
157 ///
158 /// ```rust
159 /// use mew_css::properties::color;
160 /// use mew_css::values::Color;
161 ///
162 /// let prop = color::background_color(Color::LightGray);
163 /// assert_eq!(prop.to_string(), "background-color: lightgray;");
164 ///
165 /// let prop = color::background_color(Color::Rgba(240, 240, 240, 0.5));
166 /// assert_eq!(prop.to_string(), "background-color: rgba(240, 240, 240, 0.5);");
167 /// ```
168 pub fn background_color(value: Color) -> Property {
169 Property::new("background-color", value)
170 }
171
172 /// Creates a CSS `border-color` property for setting element border color.
173 ///
174 /// The `border-color` property sets the color of an element's border on all sides.
175 /// It only has a visible effect when the border style is not `none`.
176 ///
177 /// # Arguments
178 ///
179 /// * `value` - The color value to use
180 ///
181 /// # Returns
182 ///
183 /// A new `Property` instance representing the border-color property
184 ///
185 /// # Examples
186 ///
187 /// ```rust
188 /// use mew_css::properties::color;
189 /// use mew_css::values::Color;
190 ///
191 /// let prop = color::border_color(Color::Black);
192 /// assert_eq!(prop.to_string(), "border-color: black;");
193 /// ```
194 pub fn border_color(value: Color) -> Property {
195 Property::new("border-color", value)
196 }
197}
198
199/// Size properties
200pub mod size {
201 use super::*;
202
203 /// Create a width property
204 pub fn width(value: Size) -> Property {
205 Property::new("width", value)
206 }
207
208 /// Create a height property
209 pub fn height(value: Size) -> Property {
210 Property::new("height", value)
211 }
212
213 /// Create a margin property
214 pub fn margin(value: Size) -> Property {
215 Property::new("margin", value)
216 }
217
218 /// Create a margin-top property
219 pub fn margin_top(value: Size) -> Property {
220 Property::new("margin-top", value)
221 }
222
223 /// Create a margin-right property
224 pub fn margin_right(value: Size) -> Property {
225 Property::new("margin-right", value)
226 }
227
228 /// Create a margin-bottom property
229 pub fn margin_bottom(value: Size) -> Property {
230 Property::new("margin-bottom", value)
231 }
232
233 /// Create a margin-left property
234 pub fn margin_left(value: Size) -> Property {
235 Property::new("margin-left", value)
236 }
237
238 /// Create a padding property
239 pub fn padding(value: Size) -> Property {
240 Property::new("padding", value)
241 }
242
243 /// Create a padding-top property
244 pub fn padding_top(value: Size) -> Property {
245 Property::new("padding-top", value)
246 }
247
248 /// Create a padding-right property
249 pub fn padding_right(value: Size) -> Property {
250 Property::new("padding-right", value)
251 }
252
253 /// Create a padding-bottom property
254 pub fn padding_bottom(value: Size) -> Property {
255 Property::new("padding-bottom", value)
256 }
257
258 /// Create a padding-left property
259 pub fn padding_left(value: Size) -> Property {
260 Property::new("padding-left", value)
261 }
262
263 /// Create a font-size property
264 pub fn font_size(value: Size) -> Property {
265 Property::new("font-size", value)
266 }
267
268 /// Create a line-height property
269 pub fn line_height(value: Size) -> Property {
270 Property::new("line-height", value)
271 }
272
273 /// Create a border-width property
274 pub fn border_width(value: Size) -> Property {
275 Property::new("border-width", value)
276 }
277}
278
279/// Display properties
280pub mod display {
281 use super::*;
282
283 /// Create a display property
284 pub fn display(value: Display) -> Property {
285 Property::new("display", value)
286 }
287
288 /// Create a position property
289 pub fn position(value: Position) -> Property {
290 Property::new("position", value)
291 }
292
293 /// Create a flex-direction property
294 pub fn flex_direction(value: FlexDirection) -> Property {
295 Property::new("flex-direction", value)
296 }
297
298 /// Create a justify-content property
299 pub fn justify_content(value: JustifyContent) -> Property {
300 Property::new("justify-content", value)
301 }
302
303 /// Create an align-items property
304 pub fn align_items(value: AlignItems) -> Property {
305 Property::new("align-items", value)
306 }
307}
308
309/// Font properties
310pub mod font {
311 use super::*;
312
313 /// Create a font-weight property
314 pub fn font_weight(value: FontWeight) -> Property {
315 Property::new("font-weight", value)
316 }
317
318 /// Create a font-family property
319 pub fn font_family(value: &str) -> Property {
320 Property::new("font-family", value)
321 }
322
323 /// Create a text-align property
324 pub fn text_align(value: TextAlign) -> Property {
325 Property::new("text-align", value)
326 }
327
328 /// Create a font-size property with FontSize enum
329 pub fn font_size_enum(value: FontSize) -> Property {
330 Property::new("font-size", value)
331 }
332
333 /// Create a line-height property with LineHeight enum
334 pub fn line_height_enum(value: LineHeight) -> Property {
335 Property::new("line-height", value)
336 }
337
338 /// Create a text-decoration property
339 pub fn text_decoration(value: TextDecoration) -> Property {
340 Property::new("text-decoration", value)
341 }
342}
343
344/// Border properties
345pub mod border {
346 use super::*;
347
348 /// Create a border-style property
349 pub fn border_style(value: BorderStyle) -> Property {
350 Property::new("border-style", value)
351 }
352
353 /// Create a border-radius property
354 pub fn border_radius(value: Size) -> Property {
355 Property::new("border-radius", value)
356 }
357
358 /// Create a border property (shorthand)
359 pub fn border(width: Size, style: BorderStyle, color: Color) -> Property {
360 Property::new("border", format!("{} {} {}", width, style, color))
361 }
362
363 /// Create a border-top property (shorthand)
364 pub fn border_top(width: Size, style: BorderStyle, color: Color) -> Property {
365 Property::new("border-top", format!("{} {} {}", width, style, color))
366 }
367
368 /// Create a border-right property (shorthand)
369 pub fn border_right(width: Size, style: BorderStyle, color: Color) -> Property {
370 Property::new("border-right", format!("{} {} {}", width, style, color))
371 }
372
373 /// Create a border-bottom property (shorthand)
374 pub fn border_bottom(width: Size, style: BorderStyle, color: Color) -> Property {
375 Property::new("border-bottom", format!("{} {} {}", width, style, color))
376 }
377
378 /// Create a border-left property (shorthand)
379 pub fn border_left(width: Size, style: BorderStyle, color: Color) -> Property {
380 Property::new("border-left", format!("{} {} {}", width, style, color))
381 }
382
383 /// Create a box-shadow property
384 pub fn box_shadow(value: BoxShadow) -> Property {
385 Property::new("box-shadow", value)
386 }
387
388 /// Create a box-shadow property with none value
389 pub fn box_shadow_none() -> Property {
390 Property::new("box-shadow", "none")
391 }
392}
393
394/// Position properties
395pub mod position {
396 use super::*;
397
398 /// Create a top property
399 pub fn top(value: Size) -> Property {
400 Property::new("top", value)
401 }
402
403 /// Create a right property
404 pub fn right(value: Size) -> Property {
405 Property::new("right", value)
406 }
407
408 /// Create a bottom property
409 pub fn bottom(value: Size) -> Property {
410 Property::new("bottom", value)
411 }
412
413 /// Create a left property
414 pub fn left(value: Size) -> Property {
415 Property::new("left", value)
416 }
417
418 /// Create a z-index property
419 pub fn z_index(value: ZIndex) -> Property {
420 Property::new("z-index", value)
421 }
422}
423
424/// Layout properties
425pub mod layout {
426 use super::*;
427
428 /// Create an overflow property
429 pub fn overflow(value: Overflow) -> Property {
430 Property::new("overflow", value)
431 }
432
433 /// Create an overflow-x property
434 pub fn overflow_x(value: Overflow) -> Property {
435 Property::new("overflow-x", value)
436 }
437
438 /// Create an overflow-y property
439 pub fn overflow_y(value: Overflow) -> Property {
440 Property::new("overflow-y", value)
441 }
442
443 /// Create a visibility property
444 pub fn visibility(value: Visibility) -> Property {
445 Property::new("visibility", value)
446 }
447
448 /// Create an opacity property
449 pub fn opacity(value: f32) -> Property {
450 // Ensure opacity is between 0 and 1
451 let clamped = value.max(0.0).min(1.0);
452 Property::new("opacity", clamped)
453 }
454
455 /// Create a cursor property
456 pub fn cursor(value: Cursor) -> Property {
457 Property::new("cursor", value)
458 }
459}
460
461/// Flex properties
462pub mod flex {
463 use super::*;
464
465 /// Create a gap property
466 pub fn gap(value: Size) -> Property {
467 Property::new("gap", value)
468 }
469
470 /// Create a row-gap property
471 pub fn row_gap(value: Size) -> Property {
472 Property::new("row-gap", value)
473 }
474
475 /// Create a column-gap property
476 pub fn column_gap(value: Size) -> Property {
477 Property::new("column-gap", value)
478 }
479}
480
481/// Grid properties
482pub mod grid {
483 use super::*;
484
485 /// Create a grid-template-columns property
486 pub fn grid_template_columns(value: &str) -> Property {
487 Property::new("grid-template-columns", value)
488 }
489
490 /// Create a grid-template-rows property
491 pub fn grid_template_rows(value: &str) -> Property {
492 Property::new("grid-template-rows", value)
493 }
494}
495
496/// Transition properties
497pub mod transition {
498 use super::*;
499
500 /// Create a transition property
501 pub fn transition(value: Transition) -> Property {
502 Property::new("transition", value)
503 }
504
505 /// Create a transition property with none value
506 pub fn transition_none() -> Property {
507 Property::new("transition", "none")
508 }
509
510 /// Create a transition property with all value
511 pub fn transition_all(duration: f32, timing_function: Option<&str>, delay: Option<f32>) -> Property {
512 let mut value = format!("all {}s", duration);
513
514 if let Some(timing) = timing_function {
515 value.push_str(&format!(" {}", timing));
516 }
517
518 if let Some(delay_val) = delay {
519 value.push_str(&format!(" {}s", delay_val));
520 }
521
522 Property::new("transition", value)
523 }
524}
525
526/// Size properties extension
527pub mod size_ext {
528 use super::*;
529
530 /// Create a max-width property
531 pub fn max_width(value: Size) -> Property {
532 Property::new("max-width", value)
533 }
534
535 /// Create a min-width property
536 pub fn min_width(value: Size) -> Property {
537 Property::new("min-width", value)
538 }
539
540 /// Create a max-height property
541 pub fn max_height(value: Size) -> Property {
542 Property::new("max-height", value)
543 }
544
545 /// Create a min-height property
546 pub fn min_height(value: Size) -> Property {
547 Property::new("min-height", value)
548 }
549}