yew/docs/concepts/html/classes.md
Cecile Tonglet 9737fe77db
Extract Classes to a separate macro (#1601)
* Initial commit

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* Add feature flag for now

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* Add macro classes!()

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* rustfmt

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* CLEANUP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* CLEANUP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* CLEANUP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* rustfmt

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* Not sure why there is a prelude.rs file here...

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* CLEANUP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* CLEANUP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* Revert example changes

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* CLEANUP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* WIP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* CLEANUP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* CLEANUP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* CLEANUP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* CLEANUP

Forked at: 7e6d6c43f0aa98d78ae34654d49e1cf84d252cce
Parent branch: yewstack/master

* Revert back to e2717ae6281691f9563079ef07b56b24b6431ff1

* Put back original class behavior in html!

* Store span and use quote_spanned!

* Deprecation warning

* Better error message

* cargo fmt & fix conflict leftover oops

* Fix clippy: missing import

* What have I done

* Use Token! instead of Comma

* Apply suggestion

* Renamed HtmlClasses to Classes

* Remove clippy attribute & add dedicated tests

* Remove span from Single variant

* Spacing stuff with quote_spanned!

* Removed "use" and use path to Classes

* Some doc

* Replace Vec<Expr> with ExprTuple

* rustfmt

* Move classes to its own module

* Move tests from vtag to classes

* Update classes-fail.stderr

* Check for spaces in string literals

* Use unchecked_push for string literals

* Fixed tests

* More doc

* Tested doc in browser and make boolinator import visible

* Improve doc a tad bit

* Stuff

* Fix due to change with string literal

* Typo

* Moved classes to html

* Update macro new path for Classes

* Test fix

* Example fix

* Update classes-fail.stderr

* Fixed weird error

* Update yew/src/lib.rs

Co-authored-by: Simon <simon@siku2.io>

* Update yew/Cargo.toml

* Update yew/src/html/classes.rs

Co-authored-by: Simon <simon@siku2.io>

* Update docs/concepts/html/classes.md

Co-authored-by: Simon <simon@siku2.io>

* I blame GitHub

* Use syn::Result

* Apply suggestions

* Update yew-macro/src/classes/mod.rs

Co-authored-by: Simon <simon@siku2.io>

* Update yew-macro/tests/macro_test.rs

Co-authored-by: Simon <simon@siku2.io>

* Replaced html! by classes!

* Moved classes tests

* Renamed doc title

* Apply suggestion

* Update yew-macro/src/html_tree/html_element.rs

Co-authored-by: Simon <simon@siku2.io>

* Fixed span badly handled in macro

* no implicit prelude

* Update yew/src/lib.rs

Co-authored-by: Simon <simon@siku2.io>

* Improve documentation

* Yeah... OK

* OMG clippy

* Please squash merge and don't keep my commit messages

* Safety notice

* Change "Yew's macros" to "HTML"

* Unneeded closure

* Boxing stuff 🥊

* Indentation issue

* Removed unneeded block & removed duplicated code

* Renamed "macros" to "html_macro"

* Better span

* Doc: advice to use `classes!`

* Doc: fix error and remove one "and"

* Removed interpolated example

* Remove unnecessary tests and add test for deprecated syntax

* Link to classes!

* Update yew-macro/tests/html_macro_test.rs

Co-authored-by: Simon <simon@siku2.io>

* Renamed fail test

* Apply suggestion

* WIP

* WIP

* cargo make pr-flow passes locally, let's try again

Co-authored-by: Simon <simon@siku2.io>
2020-11-25 16:32:53 +01:00

2.3 KiB

title description
Classes A handy macro to handle classes

Classes

The struct Classes can be used to deal with HTML classes.

When pushing a string to the set, Classes ensures that there is one element for every class even if a single string might contain multiple classes.

Classes can also be merged by using Extend (i.e. classes1.extend(classes2)) or push() (i.e. classes1.push(classes2)). In fact, anything that implements Into<Classes> can be used to push new classes to the set.

The macro classes! is a convenient macro that creates one single Classes. Its input accepts a comma separated list of expressions. The only requirement is that every expression implements Into<Classes>.

html! {
  <div class=classes!("container")></div>
}
html! {
  <div class=classes!("class-1", "class-2")></div>
}
let my_classes = String::from("class-1 class-2");

html! {
  <div class=classes!(my_classes)></div>
}
html! {
  <div class=classes!(Some("class")) />
}
html! {
  <div class=classes!(vec!["class-1", "class-2"])></div>
}
let my_classes = ["class-1", "class-2"];

html! {
  <div class=classes!(&my_classes)></div>
}

Components that accept classes

use boolinator::Boolinator;

#[derive(Clone, Properties)]
struct Props {
    #[prop_or_default]
    class: Classes,
    fill: bool,
    children: Children,
}

struct MyComponent {
    props: Props,
}

impl Component for MyComponent {
    type Properties = Props;

    // ...

    fn view(&self) -> Html {
        let Props {
            class,
            fill,
            children,
        } = &self.props;
        html! {
            <div
                class=classes!(
                    "my-container-class",
                    fill.as_some("my-fill-class"),
                    class.clone(),
                )
            >
                { children.clone() }
            </div>
        }
    }
}

The example makes use of the boolinator crate to conditionally add the "my-fill-class" class based on the fill boolean attribute.