#sass #scss #css #style #dioxus

sir

Write SCSS in your component functions

7 releases (4 breaking)

0.5.0 Apr 28, 2024
0.4.0 Aug 12, 2023
0.3.0 Jan 19, 2023
0.2.2 May 3, 2022
0.1.0 Apr 1, 2022

#1170 in Web programming

MIT/Apache

43KB
145 lines

Style in Rust

Write SCSS in your component functions

Usage with Dioxus

Add the dependency to Cargo.toml:

[dependencies]
sir = { version = "0.5.0", features = ["dioxus"] }

Render the AppStyle component somewhere in your app:

use sir::AppStyle;

fn App() -> Element {
    rsx!(
        AppStyle {}
        Counter {}
    )
}

Now, use the css! and global_css! macros to style your app!

use sir::{css, global_css};

fn Counter() -> Element {
    let mut count = use_signal(|| 0);

    global_css!("
        body {
            background: slategray;
        }
    ");

    let container = css!("
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 4px;
    ");

    let title = css!("color: white");

    let button = css!("
        border: none;
        padding: 8px 16px;
        border-radius: 4px;

        background: deepskyblue;
        transition: background 0.2s ease-out;

        &:hover {
            background: aquamarine;
        }
    ");

    rsx!(
        div {
            class: "{container}",
            h1 { class: "{title}", "Counter: {count}" }
            button { class: "{button}", onclick: move |_| count += 1, "Increment" }
            button { class: "{button}", onclick: move |_| count -= 1, "Decrement" }
        }
    )
}

Screenshot of result: a label "Counter: 0" with two buttons for incrementing and decrementing the counter

See examples/dioxus_counter.rs for the complete example.

Features

sir uses rsass for all the SCSS compiling. rsass is incomplete, but "usable for personal projects".

Similar Crates

Rustyle looks really cool, but it's not very well-documented and has been abandoned. It appears that Rustyle implements all parsing and code generation from scratch.

css_rs_macro from the Percy project looks promising as well, but it uses a custom, slightly more verbose syntax, and the current implementation looks a bit hacky.

Technical details

At compile time, a class name is generated for each css!() macro. The provided SCSS is wrapped in a selector for that class and compiled using rsass.

At each css! call site, some code is generated that will register the resulting CSS to the global CSS_COLLECTION variable at runtime. A static bool is used to make sure that we only register the CSS once.

Why not collect all CSS at compile time?

I could be wrong, but it seems there's no clean way to globally collect CSS at compile time. Procedural macros only work on individual items (or, experimentally, on individual files). Build scripts aren't allowed to modify source code (so we can't easily sync up generated CSS classes with what gets returned by the css! macro), and would have to do source code parsing on their own (error-prone and messy).

There's also linkme which could push some work to link time, but it appears to have been abandoned.

Dependencies

~3–8.5MB
~81K SLoC