leptos_scoped_style/lib.rs
1//! # leptos-scoped-style
2//!
3//! Scoped CSS for [Leptos](https://leptos.dev) components with emulated view
4//! encapsulation — the same technique used by Angular.
5//!
6//! ## How it works
7//!
8//! When a component mounts, `leptos-scoped-style`:
9//!
10//! 1. **Rewrites CSS selectors** at first mount — every selector gets a unique
11//! attribute appended (e.g. `button[_leptoscontent-c1a2b3c4]`), so styles
12//! are isolated to that component's own DOM nodes.
13//! 2. **Injects a `<style>` element** into `<head>` with the scoped CSS.
14//! 3. **Tags every child DOM element** with `_leptoscontent-{id}=""` so the
15//! rewritten selectors match.
16//! 4. **Tags the host wrapper** with `_leptoshost-{id}=""` for `:host` rules.
17//! 5. **Removes the `<style>`** when the last instance of the component is
18//! destroyed.
19//!
20//! ## Quick start
21//!
22//! ```rust,ignore
23//! use leptos::prelude::*;
24//! use leptos_scoped_style::{ComponentStyle, Scoped};
25//!
26//! // Declare once per component — usually at the top of the module.
27//! static BTN: ComponentStyle = ComponentStyle::css(
28//! "my-button", // must be unique in your application
29//! ":host { display: inline-block; }
30//! button { color: red; }
31//! button:hover { color: darkred; }",
32//! );
33//!
34//! #[component]
35//! fn MyButton(label: String) -> impl IntoView {
36//! view! {
37//! <Scoped style=&BTN>
38//! <button>{label}</button>
39//! </Scoped>
40//! }
41//! }
42//! ```
43//!
44//! ## Sass / SCSS (`scss_file` feature)
45//!
46//! Enable the `scss_file` feature and use [`scss_file!`] with a path **relative
47//! to your crate root** (the package that contains the `scss_file!` call).
48//! Compilation runs at **macro expansion time** (`cargo build`), so `@use` /
49//! `@forward` resolve the same way as on-disk Sass in apps and library crates.
50//!
51//! ```toml
52//! leptos-scoped-style = { version = "0.1", features = ["scss_file"] }
53//! ```
54//!
55//! ```rust,ignore
56//! use leptos_scoped_style::{ComponentStyle, scss_file, Scoped};
57//!
58//! static BTN: ComponentStyle = ComponentStyle::css(
59//! "my-button",
60//! scss_file!("src/components/button/button.scss"),
61//! );
62//! ```
63//!
64//! For **global** tokens (`:root`, universal `* { … }`), use
65//! [`ComponentStyle::global_css`] and mount once with [`GlobalStyles`].
66//!
67//! ## Supported CSS patterns
68//!
69//! | You write | Rendered as |
70//! |---|---|
71//! | `div { }` | `div[_leptoscontent-{id}] { }` |
72//! | `a:hover { }` | `a[_leptoscontent-{id}]:hover { }` |
73//! | `input::placeholder { }` | `input[_leptoscontent-{id}]::placeholder { }` |
74//! | `:host { }` | `[_leptoshost-{id}] { }` |
75//! | `:host(.active) { }` | `[_leptoshost-{id}].active { }` |
76//! | `:host .child { }` | `[_leptoshost-{id}] [_leptoscontent-{id}] { }` |
77//! | `:host:hover { }` | `[_leptoshost-{id}]:hover { }` |
78//! | `:host:hover .x { }` | `[_leptoshost-{id}]:hover .x[_leptoscontent-{id}] { }` |
79//! | `:root { }` | unchanged (global document root) |
80//! | `:skip-scope(sel)` | `sel` unchanged — no content-attribute rewrite |
81//! | `@media (…) { div { } }` | at-rule passed through; inner selectors scoped |
82
83mod css;
84mod dom;
85mod registry;
86mod scope_id;
87mod style;
88
89pub mod component;
90
91// ── Public re-exports ─────────────────────────────────────────────────────
92
93pub use component::{GlobalStyles, Scoped, ScopedChildren};
94pub use scope_id::ScopeId;
95pub use style::ComponentStyle;
96
97/// Compile an SCSS file to CSS at **macro expansion time** and embed the result
98/// as a `&'static str` expression.
99///
100/// The path is **relative to the invoking crate's** `CARGO_MANIFEST_DIR` (the
101/// package being compiled), so `@use` / `@forward` work inside component
102/// libraries—not only in the app crate.
103///
104/// Requires the `scss_file` crate feature.
105///
106/// # Example
107/// ```rust,ignore
108/// use leptos_scoped_style::{ComponentStyle, scss_file};
109///
110/// static BTN: ComponentStyle = ComponentStyle::css(
111/// "my-button",
112/// scss_file!("src/components/button/button.scss"),
113/// );
114/// ```
115#[cfg(feature = "scss_file")]
116pub use leptos_scoped_style_macros::scss_file;