Attribute macros C!
, style!
and attrs!
represent HTML element attributes in the Seed world, e.g.:
div![
C!["counter", IF!(selected => "active")],
style!{
St::Display => "flex",
St::Padding => px(10),
},
attrs!{At::Title => "A Title"},
"This is a counter.",
]
becomes
<div class="counter active" title="A Title" style="display:flex;padding:10px">
This is a counter.
</div>
C!
accepts all items that implement trait ToClasses.C!
invocations in one element, then the classes will be merged. (This rule is valid for all attributes.)ToClasses
is implemented for String
and &str
, references and containers Option
and Vec
.
Example of some valid input type combinations:
let selected = false;
let optional_classes: Option<Vec<String>> = None;
div![
C!["counter", IF!(selected => "active")],
C![IF!(true => vec!["class_a", "class_b"])],
C![optional_classes],
]
Corresponding HTML:
<div class="counter class_a class_b"></div>
The name C
breaks Rust naming conventions (macros should be written in snake_case!
), but it's a trade-off for better scannability (you can distinguish element macros and attribute macros on the first glance). And it will be consistent with future names of other entities (e.g. A.
for other attributes and E.
for event handlers).
Note: If you want to use Tailwind CSS and typed classes, look at seed-quickstart-webpack.
style!
expects key-value pairs, where:
Key is a CSS property name - e.g. St::Display
St::from("custom_name")
Value can be everything that implements ToString and it can be wrapped in Option
.
Example of some valid input type combinations:
let selected = true;
let apply_custom = true;
div![
style!{
St::Margin => px(50),
St::MaxWidth => unit!(50, %),
St::Top => 0,
St::Padding => px(20) + " " + &px(15)
St::BackgroundColor => if selected { "green" } else { "white" },
St::from("custom_name") => IF!(apply_custom => "a_value"),
}
]
Corresponding HTML:
<div style="
margin:50px;
max-width:50%;
top:0;
padding:20px 15px;
background-color:green;
custom_name:a_value
"></div>
Macro style!
will be replaced with Seed Style.
Seed Style is basically typed inline CSS on steroids. It allows you to write also pseudo-classes like :hover
directly in your Rust elements so it eliminates the need to write standalone style files. And there are many more useful features.
attrs!
expects key-value pairs, where:
Key is an attribute name - e.g. At::Title
At::from("custom_name")
Value can be AtValue or everything that implements ToString. AtValue
has 3 variants:
Ignored
- The whole attribute is ignored (i.e. not rendered to HTML at all). It's useful for boolean HTML attributes and in your conditions.None
- The attribute value is not used (i.e. rendered as empty string). It's also useful for boolean HTML attributes.Some(String)
- If v
in At::X => v
, implements ToString
, then it's automatically transformed to AtValue::Some(v)
.Note: C!
and style!
are basically only attrs!
's specializations - you can write
attrs!{At::Class => "class_a", At::Style => "top:0"}
but it's not recommended.
as_at_value
Method as_at_value
is automatically attached to all Rust bool
s. It helps with boolean attributes. It allows you to write:
let disabled = false;
...
attrs!{
At::Disabled => disabled.as_at_value()
}
instead of:
attrs!{
At::Disabled => if disabled { AtValue::None } else { AtValue::Ignored }
}
Note: Without that .as_at_value()
call, variable disabled
would be only casted into String
and rendered in HTML as disabled="false"
.
attrs!
examplelet disabled = true;
div![
attrs! {
At::Disabled => disabled.as_at_value(),
At::Title => "a_title",
At::AutoFocus => AtValue::None,
At::from("custom_name") => 123,
}
]
Corresponding HTML:
<div disabled="" title="a_title" autofocus="" custom_name="123"></div>
Macro attrs!
will be replaced with a safer and more readable API that consists struct A
and associated methods. You can see drafts in this issue.