Getting Started

Here's a basic counter component:

pub use hobo::{
    prelude::*, 
    create as e,
    signals::signal::{Mutable, SignalExt}
}

// <div class="s-f4d1763947b5e1ff">
//   <div>Counter value is: 0</div>
//   <button>increment</button>
//   <button>decrement</button>
// </div>

fn counter() -> impl hobo::AsElement {
    let counter_value = Mutable::new(0_i32);

    e::div()
        .class((
            // enum-like properties can also be set like `css::Display::Flex`
            css::display!(flex),
            css::width!(400 px),
            // #AA0000FF or #AA0000 or #A00 in normal css
            css::background_color!(rgb 0xAA_00_00),
            css::align_items!(center),
            css::justify_content!(space-between),
        ))
        .child(e::div()
            .text_signal(counter_value.signal().map(|value| {
                format!("Counter value is: {}", value)
            }))
        )
        .component(counter_value)
        .with(move |&counter_div| counter_div
            .child(e::button()
                .class(css::style!(
                    // .& is replaced with "current" class name, similar to SASS
                    // or styled-components
                    .& {
                        // shortcut for padding-left and padding-right
                        css::padding_horizontal!(16 px),
                        css::background_color!(css::color::PALEVIOLETRED),
                    }

                    .&:hover {
                        css::background_color!(css::color::GREEN),
                    }
                ))
                .text("increment")
                .on_click(move |_| {
                    *counter_div.get_cmp::<Mutable<i32>>().lock_mut() += 1;
                })
            )
            .add_child(e::button() // same as .child but non-chaining
                // since this style is identical to the one above it - the class will be
                // reused to avoid copypasting - the button generating code can be
                // moved into a function or maybe just the code that defines the style
                .class(css::style!(
                    .& {
                        css::padding_horizontal!(16 px),
                        css::background_color!(css::color::PALEVIOLETRED),
                    }

                    .&:hover {
                        css::background_color!(css::color::GREEN),
                    }
                ))
                .text("decrement")
                .on_click(move |_| {
                    *counter_div.get_cmp::<Mutable<i32>>().lock_mut() -= 1;
                })
            )
        )
}