maud
maud copied to clipboard
Optional concatenation in attribute blocks
I'm using tailwindcss, it uses a lot of classes that are annoying to write in rust/maud: mt-8
, space-y-6
etc...
So, I usually resort to write div class="mt-8 space-y-6"
, and sometimes even
div class={
"mt-8 etc..."
}
Now, currently maud supports having concatenating multiple strings like this:
div class={
"mt-8 "
"space-y-6"
}
(notice the extra space in the first, since no additional space is added here sadly)
Now, I would like to be able to have an optional class in this situation. I did not find a suitable feature in this situation, so I would suggest something akin to this:
let optional_error_classes: Option<String>;
// ...
div class={
"mt-8 "
[optional_error_classes]
}
With None
simply being handled as ""
and the content otherwise.
What do you think?
Hi @TheNeikos!
Sorry about the late response 😅
Do you know about the class shorthand syntax? We can get something similar with the following:
let has_space: bool;
// ...
div ."mt-8" ."space-y-6"[has_space]
https://maud.lambda.xyz/elements-attributes.html#classes-and-ids-foo-bar https://maud.lambda.xyz/splices-toggles.html#toggles-foo
If you need to support Option<String>
specifically, then we could add a .[some_option]
syntax, similar to the existing attr=[some_option]
syntax for optional attributes. But I want to check if this is needed first.
I would love to have .[aoptionalclassname]
rationale:
when using bulma I sometimes want to apply one of the Color modifier classes (is-primary, is-danger) computed at runtime, sadly the neutral Color in bulma is indicated by the absence of any indicator…
@bgrundmann does .is-primary[state == State::Primary].is-danger[state == State::Danger]
work for you?
Do you know about the class shorthand syntax? We can get something similar with the following:
let has_space: bool; // ... div ."mt-8" ."space-y-6"[has_space]
Yes that is true, but I find writing .""
very cumbersome for the 10+ classes tailwind sometimes requires.
@bgrundmann does
.is-primary[state == State::Primary].is-danger[state == State::Danger]
work for you?
Sorry for the late reply my GitHub email notifications got lost in my inbox. Yeah that works. That said the '.[aoptionalclassname]' would I think in the end read better. But I can understand not wanting to make the language too complicated.
I would love to have
.[aoptionalclassname]
Oh that sounds good to me. I don't think it makes the language more complicated, since it's "filling in a hole" (so to speak).
Can't you use @if let Some
?
How about:
#[derive(Clone, Default, Debug, PartialEq, strum_macros::Display)]
pub enum Color {
#[default]
#[strum(serialize = "")]
Default,
#[strum(serialize = "is-success")]
Success,
#[strum(serialize = "is-warning")]
Warning,
#[strum(serialize = "is-danger")]
Danger,
#[strum(serialize = "is-info")]
Info,
}
#[derive(Clone, Default, Debug, PartialEq, strum_macros::Display)]
pub enum Size {
#[strum(serialize = "is-small")]
Small,
#[default]
#[strum(serialize = "")]
Default,
#[strum(serialize = "is-medium")]
Medium,
#[strum(serialize = "is-large")]
Large,
}
And using it like:
let state = Color::Danger;
let size = Size::Large;
html! {
.message (size) (state) {
.message-body {
"Hamburgefontsiv"
}
}
}
You can even make it more compact by using strum's kebab-case conversion:
#[derive(Clone, Default, Debug, PartialEq, strum_macros::Display)]
#[strum(serialize_all = "kebab-case")]
pub enum Size {
IsSmall,
IsMedium,
IsLarge,
}