futursolo / stylist-rs

A CSS-in-Rust styling solution for WebAssembly Applications
https://crates.io/crates/stylist
MIT License
366 stars 22 forks source link

Performance: Variables, or Binding? #79

Closed simbleau closed 2 years ago

simbleau commented 2 years ago

I have a curious question. My goal is to reduce the amount of hook calls and receive the best performance. My idea is to bind 2 variables, --bg and --fg to a theme and set them into the :root. I imagine that I might may not need a ThemeContext to wrap the entire App this way, and let the browser re-render on variable changes.

Which is faster - Binding the colors directly or using variables and letting the browser re-render on variable changes?

Variable approach:

fn variables() -> StyleSource<'static> {
    let theme = use_theme();
    css!(
        r#"
            :root {
                --bg: ${bg},
                --fg: ${fg},
            }
        "#,
        bg = theme.bg1.to_css(),
        fg = thene.fg1.to_css(),
    )
}

#[function_component(Root)]
pub fn root() -> Html {
    html! {
        <ThemeProvider>
            <Global css={ variables() } />
            <ThemeSwitcher />
        </ThemeProvider>
        <App />
    }
}

#[function_component(ThemeSwitcher)]
pub fn theme_switcher() -> Html {
    let theme = use_theme();
    let other_theme = match theme.kind() {
        ThemeChoice::Light => ThemeChoice::Dark,
        ThemeChoice::Dark => ThemeChoice::Light,
    };
    let switch_theme = Callback::from(move |_| theme.set(other_theme));

    html! {
        <button onclick={ switch_theme }>
            { "switch" }
        </button>
    }
}

#[function_component(App)]
fn app() -> Html {
    html! {
        <>
        <h2 class={css!("color: var(--fg)")}>
            { "Hello!" }
        </h2>
        </>
    }
}

Binding colors directly:

fn variables() -> StyleSource<'static> {
    let theme = use_theme();
    css!(
        r#"
            :root {
                bakcground-color: ${bg},
                color: ${fg},
            }
        "#,
        bg = theme.bg1.to_css(),
        fg = thene.fg1.to_css(),
    )
}