dioxus_style 0.5.3

Scoped CSS/SCSS styling system for Dioxus components with compile-time processing and SCSS support
Documentation
# 🎨 Dioxus Style


**The Ultimate Styling Solution for Dioxus**  
*Type-Safe. Compile-Time. SCSS-Powered.*

[![Crates.io](https://img.shields.io/crates/v/dioxus_style.svg)](https://crates.io/crates/dioxus_style)
[![Documentation](https://docs.rs/dioxus_style/badge.svg)](https://docs.rs/dioxus_style)
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](LICENSE-MIT)

---

## 🧐 Why Dioxus Style?


Writing CSS in Rust often feels like a compromise. You either have to use loose strings (`class: "btn primary"`) which hides typos until runtime, or use heavy runtime libraries that slow down your app.

**Dioxus Style changes the game:**

1.  **🛡️ Zero Runtime Cost (Almost)**: Your SCSS is compiled to CSS **during the build**. The browser just loads a static CSS string.
2.  **✅ Type Safety**: Your CSS classes become **Rust Constants**. If you type `style::buttn` instead of `style::button`, your code **won't compile**. No more UI bugs because of a typo!
3.  **💪 SCSS Built-In**: Use variables, nesting, and mixins right out of the box. No external build tools needed.
4.  **⚡ Hot Reload Friendly**: Change your `.scss` file, and the app updates instantly.

---

## 📦 Installation


Add this to your `Cargo.toml`.

```toml
[dependencies]
dioxus_style = "0.5.3"
```

*Note: SCSS support is enabled by default. If you only want CSS, you can disable default features.*

---

## 🚀 Step-by-Step Guide


### 1. Create your SCSS file

Create a standard SCSS file anywhere in your project (e.g., `src/button.scss`).

```scss
// src/button.scss
$primary: #6200ea;

.container {
    display: flex;
    gap: 10px;
}

.btn {
    background-color: $primary;
    color: white;
    padding: 8px 16px;
    border-radius: 4px;

    &:hover {
        opacity: 0.9;
    }
    
    // Defines a modifier class
    &.outlined {
        background: transparent;
        border: 2px solid $primary;
        color: $primary;
    }
}
```

### 2. Connect it to your Component

Use the `#[with_css]` macro to load the file. This does two things:
1. Compiles the SCSS to Scoped CSS.
2. Creates a Rust module (named `style` in the example below) containing your classes.

```rust
use dioxus::prelude::*;
use dioxus_style::with_css;

// usage: #[with_css(MODULE_NAME, "PATH_TO_FILE")]
#[with_css(style, "src/button.scss")]

fn ButtonComponent() -> Element {
    // ...
}
```

### 3. Use Type-Safe Classes

Now, instead of typing strings, you use the module you just created!

```rust
#[with_css(style, "src/button.scss")]

fn ButtonComponent() -> Element {
    rsx! {
        div {
            // style::container is a constant derived from your SCSS file!
            class: style::container, 

            button {
                class: style::btn,
                "Primary Button"
            }

            button {
                // ✨ MAGIC: Combine classes using the '+' operator
                class: style::btn + style::outlined,
                "Outlined Button"
            }
        }
    }
}
```

---

## 🧠 Deep Dive: How it works


### The Magic of `style::btn`

When you write `.btn { ... }` in your SCSS, the macro generates Rust code that looks like this:

```rust
// Generated automatically by the macro
mod style {
    pub const btn: CssClass = CssClass::new("sc_X7z9_btn");
    pub const outlined: CssClass = CssClass::new("sc_X7z9_outlined");
    // ...
}
```

This means:
- **Autocomplete**: Your IDE knows exactly what classes exist.
- **Refactoring**: Rename a class in SCSS? The compiler tells you where you need to update your Rust code.

### Automatic Scoping

To prevent styles from leaking (e.g., a `.container` in one component affecting another), `dioxus_style` generates unique hashes.
- Input: `.btn`
- Output: `.sc_a1b2_btn`

You never have to worry about class name collisions again.

---

## 🛠️ Advanced Usage


### Multiple Stylesheets

If you have a complex component that needs styles from multiple files (e.g., a shared theme and specific component styles), use `component_with_css!`.

```rust
use dioxus_style::component_with_css;

component_with_css! {
    // Import multiple files into different namespaces
    layout: "src/styles/layout.scss",
    theme: "src/styles/theme.scss",

    fn Dashboard() -> Element {
        rsx! {
            div {
                class: layout::grid, // From layout.scss
                
                div {
                    // Combine classes from different files!
                    class: layout::card + theme::dark_mode,
                    "Multi-styled Component"
                }
            }
        }
    }
}
```

### Manual/Inline Scoping

For one-off styles where you don't want a separate file.

```rust
use dioxus_style::scoped_style;

fn InlineExample() -> Element {
    // Compiles SCSS string immediately
    scoped_style!(css, "
        .text { color: red; font-weight: bold; }
    ");

    rsx! {
        p { class: css::text, "I am styled inline!" }
    }
}
```

---

## ❓ Frequently Asked Questions


**Q: Does this work with Tailwind?**  
A: Yes, you can use both. `dioxus_style` is great for custom complex components where Tailwind strings get too long, or for utilizing SCSS features.

**Q: Where do I put my SCSS files?**  
A: Anywhere! Paths are relative to your `Cargo.toml`. Common patterns are `src/components/MyComponent.scss` or a dedicated `assets/` folder.

**Q: I don't see my styles?**  
A: Make sure you have `style { dangerous_inner_html: "{inject_styles()}" }` in your root App component if you are NOT using the `#[with_css]` macro on the root. (Note: `#[with_css]` handles injection for you automatically in the component usage, but global styles usually need a root injector).

---

## 📜 License


This project is dual-licensed under MIT and Apache 2.0.