소스 검색

Document props and component macro (#2522)

* document prop attributes

* document children props

* fix children doc test
Evan Almloff 1 년 전
부모
커밋
3a4860add4

+ 323 - 0
packages/core-macro/docs/component.md

@@ -0,0 +1,323 @@
+# Component
+
+The component macro turns a function with arguments that are [`Clone`] and [`PartialEq`] into a component. This is the recommended way of creating most components. If you want more fine grained control over how the overall prop struct implements the `Properties` trait, you can use an explicit props struct with the [`Props`] derive macro instead.
+
+## Arguments
+
+- `no_case_check` - Doesn't enforce `PascalCase` on your component names.
+  **This will be removed/deprecated in a future update in favor of a more complete Clippy-backed linting system.**
+  The reasoning behind this is that Clippy allows more robust and powerful lints, whereas
+  macros are extremely limited.
+
+## Features
+
+This attribute:
+
+- Enforces that your component uses `PascalCase` or `snake_case` with at least one underscore.
+- Automatically creates a prop struct for your component if the function has arguments.
+- Verifies the function signature is valid as a component.
+
+## Examples
+
+- Without props:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn GreetBob() -> Element {
+    rsx! { "hello, bob" }
+}
+```
+
+- With props:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn GreetBob(bob: String) -> Element {
+    rsx! { "hello, {bob}" }
+}
+```
+
+## Prop Modifiers
+
+You can use the `#[props()]` attribute to modify the behavior of the props the component macro creates:
+
+- [`#[props(default)]`](#default-props) - Makes the field optional in the component and uses the default value if it is not set when creating the component.
+- [`#[props(!optional)]`](#optional-props) - Makes a field with the type `Option<T>` required.
+- [`#[props(into)]`](#converting-props) - Converts a field into the correct type by using the [`Into`] trait.
+- [`#[props(extends = GlobalAttributes)]`](#extending-elements) - Extends the props with all the attributes from an element or the global element attributes.
+
+Props also act slightly differently when used with:
+
+- [`Option<T>`](#optional-props) - The field is automatically optional with a default value of `None`.
+- [`ReadOnlySignal<T>`](#reactive-props) - The props macro will automatically convert `T` into `ReadOnlySignal<T>` when it is passed as a prop.
+- [`String`](#formatted-props) - The props macro will accept formatted strings for any prop field with the type `String`.
+- [`children`](#children-props) - The props macro will accept child elements if you include the `children` prop.
+
+### Default Props
+
+The `default` attribute lets you define a default value for a field if it isn't set when creating the component
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Button(
+    // The default attributes makes your field optional in the component and uses the default value if it is not set.
+    #[props(default)]
+    text: String,
+    // You can also set an explicit default value instead of using the `Default` implementation.
+    #[props(default = "red".to_string())]
+    color: String,
+) -> Element {
+    rsx! {
+        button {
+            color: color,
+            "{text}"
+        }
+    }
+}
+
+rsx! {
+    // You can skip setting props that have a default value when you use the component.
+    Button {}
+};
+```
+
+### Optional Props
+
+When defining a component, you may want to make a prop optional without defining an explicit default value. Any fields with the type `Option<T>` are automatically optional with a default value of `None`.
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Button(
+    // Since the `text` field is optional, you don't need to set it when you use the component.
+    text: Option<String>,
+) -> Element {
+    rsx! {
+        button { {text.unwrap_or("button".to_string())} }
+    }
+}
+
+rsx! {
+    Button {}
+};
+```
+
+If you want to make your `Option<T>` field required, you can use the `!optional` attribute:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Button(
+    // You can use the `!optional` attribute on a field with the type `Option<T>` to make it required.
+    #[props(!optional)]
+    text: Option<String>,
+) -> Element {
+    rsx! {
+        button { {text.unwrap_or("button".to_string())} }
+    }
+}
+
+rsx! {
+    Button {
+        text: None
+    }
+};
+```
+
+### Converting Props
+
+You can automatically convert a field into the correct type by using the `into` attribute. Any type you pass into the field will be converted with the [`Into`] trait:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Button(
+    // You can use the `into` attribute on a field to convert types you pass in with the Into trait.
+    #[props(into)]
+    number: u64,
+) -> Element {
+    rsx! {
+        button { "{number}" }
+    }
+}
+
+rsx! {
+    Button {
+        // Because we used the into attribute, we can pass in any type that implements Into<u64>
+        number: 10u8
+    }
+};
+```
+
+### Formatted Props
+
+You can use formatted strings in attributes just like you would in an element. Any prop field with the type `String` can accept a formatted string:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Button(text: String,) -> Element {
+    rsx! {
+        button { "{text}" }
+    }
+}
+
+let name = "Bob";
+rsx! {
+    Button {
+        // You can use formatted strings in props that accept String just like you would in an element.
+        text: "Hello {name}!"
+    }
+};
+```
+
+### Children Props
+
+Rather than passing the RSX through a regular prop, you may wish to accept children similarly to how elements can have children. The "magic" children prop lets you achieve this:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Clickable(
+    href: String,
+    children: Element,
+) -> Element {
+    rsx! {
+        a {
+            href: "{href}",
+            class: "fancy-button",
+            {children}
+        }
+    }
+}
+```
+
+This makes providing children to the component much simpler: simply put the RSX inside the {} brackets:
+
+```rust, no_run
+# use dioxus::prelude::*;
+# #[component]
+# fn Clickable(
+#     href: String,
+#     children: Element,
+# ) -> Element {
+#     rsx! {
+#         a {
+#             href: "{href}",
+#             class: "fancy-button",
+#             {children}
+#         }
+#     }
+# }
+rsx! {
+    Clickable {
+        href: "https://www.youtube.com/watch?v=C-M2hs3sXGo",
+        "How to "
+        i { "not" }
+        " be seen"
+    }
+};
+```
+
+### Reactive Props
+
+In dioxus, when a prop changes, the component will rerun with the new value to update the UI. For example, if count changes from 0 to 1, this component will rerun and update the UI to show "Count: 1":
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Counter(count: i32) -> Element {
+    rsx! {
+        div {
+            "Count: {count}"
+        }
+    }
+}
+```
+
+Generally, just rerunning the component is enough to update the UI. However, if you use your prop inside reactive hooks like `use_memo` or `use_resource`, you may also want to restart those hooks when the prop changes:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Counter(count: i32) -> Element {
+    // We can use a memo to calculate the doubled count. Since this memo will only be created the first time the component is run and `count` is not reactive, it will never update when `count` changes.
+    let doubled_count = use_memo(move || count * 2);
+    rsx! {
+        div {
+            "Count: {count}"
+            "Doubled Count: {doubled_count}"
+        }
+    }
+}
+```
+
+To fix this issue you can either:
+
+1. Make the prop reactive by wrapping it in `ReadOnlySignal` (recommended):
+
+`ReadOnlySignal` is a `Copy` reactive value. Dioxus will automatically convert any value into a `ReadOnlySignal` when it is passed as a prop.
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Counter(count: ReadOnlySignal<i32>) -> Element {
+    // Since we made count reactive, the memo will automatically rerun when count changes.
+    let doubled_count = use_memo(move || count() * 2);
+    rsx! {
+        div {
+            "Count: {count}"
+            "Doubled Count: {doubled_count}"
+        }
+    }
+}
+```
+
+2. Explicitly add the prop as a dependency to the reactive hook with [`use_reactive`](https://docs.rs/dioxus-hooks/latest/dioxus_hooks/macro.use_reactive.html):
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Counter(count: i32) -> Element {
+    // We can add the count prop as an explicit dependency to every reactive hook that uses it with use_reactive.
+    // The use_reactive macro takes a closure with explicit dependencies as its argument.
+    let doubled_count = use_memo(use_reactive!(|count| count * 2));
+    rsx! {
+        div {
+            "Count: {count}"
+            "Doubled Count: {doubled_count}"
+        }
+    }
+}
+```
+
+### Extending Elements
+
+The `extends` attribute lets you extend your props with all the attributes from an element or the global element attributes.
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Button(
+    // You can use the `extends` attribute on a field with the type `Vec<Attribute>` to extend the props with all the attributes from an element or the global element attributes.
+    #[props(extends = GlobalAttributes)]
+    attributes: Vec<Attribute>,
+) -> Element {
+    rsx! {
+        // Instead of copying over every single attribute, we can just spread the attributes from the props into the button.
+        button { ..attributes, "button" }
+    }
+}
+
+rsx! {
+    // Since we extend global attributes, you can use any attribute that would normally appear on the button element.
+    Button {
+        width: "10px",
+        height: "10px",
+        color: "red",
+    }
+};
+```

+ 339 - 0
packages/core-macro/docs/props.md

@@ -0,0 +1,339 @@
+# Props
+
+The props derive macro allows you to define what props your component accepts and how to accept those props. Every component must either accept no arguments or accept a single argument that implements the `Properties` trait.
+
+> Note: You should generally prefer using the `#[component]` macro instead of the `#[derive(Props)]` macro with explicit props. The `#[component]` macro will automatically generate the props struct for you and perform extra checks to ensure that your component is valid.
+
+## Example
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[derive(Props, PartialEq, Clone)]
+struct ButtonProps {
+    /// The text of the button
+    text: String,
+
+    /// The color of the button
+    color: String,
+}
+
+fn Button(props: ButtonProps) -> Element {
+    rsx! {
+        button {
+            color: props.color,
+            "{props.text}"
+        }
+    }
+}
+
+rsx! {
+    // Any fields you defined on the props struct will be turned into props for the component.
+    Button {
+        text: "Click me!",
+        color: "red",
+    }
+};
+```
+
+## Prop Modifiers
+
+You can use the `#[props()]` attribute to modify the behavior of the props derive macro:
+
+- [`#[props(default)]`](#default-props) - Makes the field optional in the component and uses the default value if it is not set when creating the component.
+- [`#[props(!optional)]`](#optional-props) - Makes a field with the type `Option<T>` required.
+- [`#[props(into)]`](#converting-props) - Converts a field into the correct type by using the [`Into`] trait.
+- [`#[props(extends = GlobalAttributes)]`](#extending-elements) - Extends the props with all the attributes from an element or the global element attributes.
+
+Props also act slightly differently when used with:
+
+- [`Option<T>`](#optional-props) - The field is automatically optional with a default value of `None`.
+- [`ReadOnlySignal<T>`](#reactive-props) - The props macro will automatically convert `T` into `ReadOnlySignal<T>` when it is passed as a prop.
+- [`String`](#formatted-props) - The props macro will accept formatted strings for any prop field with the type `String`.
+- [`children`](#children-props) - The props macro will accept child elements if you include the `children` prop.
+
+### Default Props
+
+The `default` attribute lets you define a default value for a field if it isn't set when creating the component
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[derive(Props, PartialEq, Clone)]
+struct ButtonProps {
+    // The default attributes makes your field optional in the component and uses the default value if it is not set.
+    #[props(default)]
+    text: String,
+
+    /// You can also set an explicit default value instead of using the `Default` implementation.
+    #[props(default = "red".to_string())]
+    color: String,
+}
+
+fn Button(props: ButtonProps) -> Element {
+    rsx! {
+        button {
+            color: props.color,
+            "{props.text}"
+        }
+    }
+}
+
+rsx! {
+    // You can skip setting props that have a default value when you use the component.
+    Button {}
+};
+```
+
+### Optional Props
+
+When defining props, you may want to make a prop optional without defining an explicit default value. Any fields with the type `Option<T>` are automatically optional with a default value of `None`.
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[derive(Props, PartialEq, Clone)]
+struct ButtonProps {
+    // Since the `text` field is optional, you don't need to set it when you use the component.
+    text: Option<String>,
+}
+
+fn Button(props: ButtonProps) -> Element {
+    rsx! {
+        button { {props.text.unwrap_or("button".to_string())} }
+    }
+}
+
+rsx! {
+    Button {}
+};
+```
+
+If you want to make your `Option<T>` field required, you can use the `!optional` attribute:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[derive(Props, PartialEq, Clone)]
+struct ButtonProps {
+    /// You can use the `!optional` attribute on a field with the type `Option<T>` to make it required.
+    #[props(!optional)]
+    text: Option<String>,
+}
+
+fn Button(props: ButtonProps) -> Element {
+    rsx! {
+        button { {props.text.unwrap_or("button".to_string())} }
+    }
+}
+
+rsx! {
+    Button {
+        text: None
+    }
+};
+```
+
+### Converting Props
+
+You can automatically convert a field into the correct type by using the `into` attribute. Any type you pass into the field will be converted with the [`Into`] trait:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[derive(Props, PartialEq, Clone)]
+struct ButtonProps {
+    /// You can use the `into` attribute on a field to convert types you pass in with the Into trait.
+    #[props(into)]
+    number: u64,
+}
+
+fn Button(props: ButtonProps) -> Element {
+    rsx! {
+        button { "{props.number}" }
+    }
+}
+
+rsx! {
+    Button {
+        // Because we used the into attribute, we can pass in any type that implements Into<u64>
+        number: 10u8
+    }
+};
+```
+
+### Formatted Props
+
+You can use formatted strings in attributes just like you would in an element. Any prop field with the type `String` can accept a formatted string:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[derive(Props, PartialEq, Clone)]
+struct ButtonProps {
+    text: String,
+}
+
+fn Button(props: ButtonProps) -> Element {
+    rsx! {
+        button { "{props.text}" }
+    }
+}
+
+let name = "Bob";
+rsx! {
+    Button {
+        // You can use formatted strings in props that accept String just like you would in an element.
+        text: "Hello {name}!"
+    }
+};
+```
+
+### Children Props
+
+Rather than passing the RSX through a regular prop, you may wish to accept children similarly to how elements can have children. The "magic" children prop lets you achieve this:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[derive(PartialEq, Clone, Props)]
+struct ClickableProps {
+    href: String,
+    children: Element,
+}
+
+fn Clickable(props: ClickableProps) -> Element {
+    rsx! {
+        a {
+            href: "{props.href}",
+            class: "fancy-button",
+            {props.children}
+        }
+    }
+}
+```
+
+This makes providing children to the component much simpler: simply put the RSX inside the {} brackets:
+
+```rust, no_run
+# use dioxus::prelude::*;
+# #[derive(PartialEq, Clone, Props)]
+# struct ClickableProps {
+#     href: String,
+#     children: Element,
+# }
+#
+# fn Clickable(props: ClickableProps) -> Element {
+#     rsx! {
+#         a {
+#             href: "{props.href}",
+#             class: "fancy-button",
+#             {props.children}
+#         }
+#     }
+# }
+rsx! {
+    Clickable {
+        href: "https://www.youtube.com/watch?v=C-M2hs3sXGo",
+        "How to "
+        i { "not" }
+        " be seen"
+    }
+};
+```
+
+### Reactive Props
+
+In dioxus, when a prop changes, the component will rerun with the new value to update the UI. For example, if count changes from 0 to 1, this component will rerun and update the UI to show "Count: 1":
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Counter(count: i32) -> Element {
+    rsx! {
+        div {
+            "Count: {count}"
+        }
+    }
+}
+```
+
+Generally, just rerunning the component is enough to update the UI. However, if you use your prop inside reactive hooks like `use_memo` or `use_resource`, you may also want to restart those hooks when the prop changes:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Counter(count: i32) -> Element {
+    // We can use a memo to calculate the doubled count. Since this memo will only be created the first time the component is run and `count` is not reactive, it will never update when `count` changes.
+    let doubled_count = use_memo(move || count * 2);
+    rsx! {
+        div {
+            "Count: {count}"
+            "Doubled Count: {doubled_count}"
+        }
+    }
+}
+```
+
+To fix this issue you can either:
+
+1. Make the prop reactive by wrapping it in `ReadOnlySignal` (recommended):
+
+`ReadOnlySignal` is a `Copy` reactive value. Dioxus will automatically convert any value into a `ReadOnlySignal` when it is passed as a prop.
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Counter(count: ReadOnlySignal<i32>) -> Element {
+    // Since we made count reactive, the memo will automatically rerun when count changes.
+    let doubled_count = use_memo(move || count() * 2);
+    rsx! {
+        div {
+            "Count: {count}"
+            "Doubled Count: {doubled_count}"
+        }
+    }
+}
+```
+
+2. Explicitly add the prop as a dependency to the reactive hook with [`use_reactive`](https://docs.rs/dioxus-hooks/latest/dioxus_hooks/macro.use_reactive.html):
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn Counter(count: i32) -> Element {
+    // We can add the count prop as an explicit dependency to every reactive hook that uses it with use_reactive.
+    // The use_reactive macro takes a closure with explicit dependencies as its argument.
+    let doubled_count = use_memo(use_reactive!(|count| count * 2));
+    rsx! {
+        div {
+            "Count: {count}"
+            "Doubled Count: {doubled_count}"
+        }
+    }
+}
+```
+
+### Extending Elements
+
+The `extends` attribute lets you extend your props with all the attributes from an element or the global element attributes.
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[derive(Props, PartialEq, Clone)]
+struct ButtonProps {
+    /// You can use the `extends` attribute on a field with the type `Vec<Attribute>` to extend the props with all the attributes from an element or the global element attributes.
+    #[props(extends = GlobalAttributes)]
+    attributes: Vec<Attribute>,
+}
+
+#[component]
+fn Button(props: ButtonProps) -> Element {
+    rsx! {
+        // Instead of copying over every single attribute, we can just spread the attributes from the props into the button.
+        button { ..props.attributes, "button" }
+    }
+}
+
+rsx! {
+    // Since we extend global attributes, you can use any attribute that would normally appear on the button element.
+    Button {
+        width: "10px",
+        height: "10px",
+        color: "red",
+    }
+};
+```

+ 185 - 0
packages/core-macro/docs/rsx.md

@@ -0,0 +1,185 @@
+The rsx! macro makes it easy for developers to write jsx-style markup in their components.
+
+## Elements
+
+You can render elements with rsx! with the element name and then braces surrounding the attributes and children.
+
+```rust, no_run
+# use dioxus::prelude::*;
+rsx! {
+    div {
+        div {}
+    }
+};
+```
+
+<details>
+<summary>Web Components</summary>
+
+Dioxus will automatically render any elements with `-` as a untyped web component:
+
+```rust, no_run
+# use dioxus::prelude::*;
+rsx! {
+    div-component {
+        div {}
+    }
+};
+```
+
+You can wrap your web component in a custom component to add type checking:
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn MyDivComponent(width: i64) -> Element {
+    rsx! {
+        div-component {
+            "width": width
+        }
+    }
+}
+```
+
+</details>
+
+## Attributes
+
+You can add attributes to any element inside the braces. Attributes are key-value pairs separated by a colon.
+
+```rust, no_run
+# use dioxus::prelude::*;
+let width = 100;
+rsx! {
+    div {
+        // Set the class attribute to "my-class"
+        class: "my-class",
+        // attribute strings are automatically formatted with the format macro
+        width: "{width}px",
+    }
+};
+```
+
+### Optional Attributes
+
+You can include optional attributes with an unterminated if statement as the value of the attribute:
+
+```rust, no_run
+# use dioxus::prelude::*;
+# let first_boolean = true;
+# let second_boolean = false;
+rsx! {
+    div {
+        // Set the class attribute to "my-class" if true
+        class: if first_boolean {
+            "my-class"
+        },
+        // Set the class attribute to "my-other-class" if false
+        class: if second_boolean {
+            "my-other-class"
+        }
+    }
+};
+```
+
+### Raw Attributes
+
+Dioxus defaults to attributes that are type checked as html. If you want to include an attribute that is not included in the html spec, you can use the `raw` attribute surrounded by quotes:
+
+```rust, no_run
+# use dioxus::prelude::*;
+rsx! {
+    div {
+        // Set the data-count attribute to "1"
+        "data-count": "1"
+    }
+};
+```
+
+## Text
+
+You can include text in your markup as a string literal:
+
+```rust, no_run
+# use dioxus::prelude::*;
+let name = "World";
+rsx! {
+    div {
+        "Hello World"
+        // Just like attributes, you can included formatted segments inside your text
+        "Hello {name}"
+    }
+};
+```
+
+## Components
+
+You can render any [`macro@crate::component`]s you created inside your markup just like elements. Components must either start with a capital letter or contain a `_` character.
+
+```rust, no_run
+# use dioxus::prelude::*;
+#[component]
+fn HelloWorld() -> Element {
+    rsx! { "hello world!" }
+}
+
+rsx! {
+    div {
+        HelloWorld {}
+    }
+};
+```
+
+## If statements
+
+You can use if statements to conditionally render children. The body of the for if statement is parsed as rsx markup:
+
+```rust, no_run
+# use dioxus::prelude::*;
+let first_boolean = true;
+let second_boolean = false;
+rsx! {
+    if first_boolean {
+        div {
+            "first"
+        }
+    }
+
+    if second_boolean {
+        "second"
+    }
+};
+```
+
+## For loops
+
+You can also use for loops to iterate over a collection of items. The body of the for loop is parsed as rsx markup:
+
+```rust, no_run
+# use dioxus::prelude::*;
+let numbers = vec![1, 2, 3];
+rsx! {
+    for number in numbers {
+        div {
+            "{number}"
+        }
+    }
+};
+```
+
+## Raw Expressions
+
+You can include raw expressions inside your markup inside curly braces. Your expression must implement the [`IntoDynNode`](https://docs.rs/dioxus-core/latest/dioxus_core/trait.IntoDynNode.html) trait:
+
+```rust, no_run
+# use dioxus::prelude::*;
+let name = "World";
+rsx! {
+    div {
+        // Text can be converted into a dynamic node in rsx
+        {name}
+    }
+    // Iterators can also be converted into dynamic nodes
+    {(0..10).map(|n| n * n).map(|number| rsx! { div { "{number}" } })}
+};
+```

+ 10 - 225
packages/core-macro/src/lib.rs

@@ -13,6 +13,13 @@ mod utils;
 
 use dioxus_rsx as rsx;
 
+/// Format a string with inline rust expressions. [`format_args_f!`] is very similar to [`format_args`], but it allows you to use arbitrary rust expressions inside braces instead of just variables:
+///
+/// ```rust,no_run
+/// # use dioxus::prelude::*;
+/// let formatted_with_variables = format_args!("{} + {} = {}", 1, 2, 1 + 2);
+/// let formatted_with_inline_expressions = format_args_f!("{1} + {2} = {1 + 2}");
+/// ```
 #[proc_macro]
 pub fn format_args_f(input: TokenStream) -> TokenStream {
     use rsx::*;
@@ -21,6 +28,7 @@ pub fn format_args_f(input: TokenStream) -> TokenStream {
         .into()
 }
 
+#[doc = include_str!("../docs/props.md")]
 #[proc_macro_derive(Props, attributes(props))]
 pub fn derive_typed_builder(input: TokenStream) -> TokenStream {
     let input = parse_macro_input!(input as syn::DeriveInput);
@@ -30,192 +38,7 @@ pub fn derive_typed_builder(input: TokenStream) -> TokenStream {
     }
 }
 
-/// The rsx! macro makes it easy for developers to write jsx-style markup in their components.
-///
-/// ## Elements
-///
-/// You can render elements with rsx! with the element name and then braces surrounding the attributes and children.
-///
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// rsx! {
-///     div {
-///         div {}
-///     }
-/// };
-/// ```
-///
-/// <details>
-/// <summary>Web Components</summary>
-///
-///
-/// Dioxus will automatically render any elements with `-` as a untyped web component:
-///
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// rsx! {
-///     div-component {
-///         div {}
-///     }
-/// };
-/// ```
-///
-/// You can wrap your web component in a custom component to add type checking:
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// #[component]
-/// fn MyDivComponent(width: i64) -> Element {
-///     rsx! {
-///         div-component {
-///             "width": width
-///         }
-///     }
-/// }
-/// ```
-///
-///
-/// </details>
-///
-/// ## Attributes
-///
-/// You can add attributes to any element inside the braces. Attributes are key-value pairs separated by a colon.
-///
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// let width = 100;
-/// rsx! {
-///     div {
-///         // Set the class attribute to "my-class"
-///         class: "my-class",
-///         // attribute strings are automatically formatted with the format macro
-///         width: "{width}px",
-///     }
-/// };
-/// ```
-///
-/// ### Optional Attributes
-///
-/// You can include optional attributes with an unterminated if statement as the value of the attribute:
-///
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// # let first_boolean = true;
-/// # let second_boolean = false;
-/// rsx! {
-///     div {
-///         // Set the class attribute to "my-class" if true
-///         class: if first_boolean {
-///             "my-class"
-///         },
-///         // Set the class attribute to "my-other-class" if false
-///         class: if second_boolean {
-///             "my-other-class"
-///         }
-///     }
-/// };
-/// ```
-///
-/// ### Raw Attributes
-///
-/// Dioxus defaults to attributes that are type checked as html. If you want to include an attribute that is not included in the html spec, you can use the `raw` attribute surrounded by quotes:
-///
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// rsx! {
-///     div {
-///         // Set the data-count attribute to "1"
-///         "data-count": "1"
-///     }
-/// };
-/// ```
-///
-/// ## Text
-///
-/// You can include text in your markup as a string literal:
-///
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// let name = "World";
-/// rsx! {
-///     div {
-///         "Hello World"
-///         // Just like attributes, you can included formatted segments inside your text
-///         "Hello {name}"
-///     }
-/// };
-/// ```
-///
-/// ## Components
-///
-/// You can render any [`macro@crate::component`]s you created inside your markup just like elements. Components must either start with a capital letter or contain a `_` character.
-///
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// #[component]
-/// fn HelloWorld() -> Element {
-///     rsx! { "hello world!" }
-/// }
-///
-/// rsx! {
-///     div {
-///         HelloWorld {}
-///     }
-/// };
-/// ```
-///
-/// ## If statements
-///
-/// You can use if statements to conditionally render children. The body of the for if statement is parsed as rsx markup:
-///
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// let first_boolean = true;
-/// let second_boolean = false;
-/// rsx! {
-///     if first_boolean {
-///         div {
-///             "first"
-///         }
-///     }
-///
-///     if second_boolean {
-///         "second"
-///     }
-/// };
-/// ```
-///
-/// ## For loops
-///
-/// You can also use for loops to iterate over a collection of items. The body of the for loop is parsed as rsx markup:
-///
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// let numbers = vec![1, 2, 3];
-/// rsx! {
-///     for number in numbers {
-///         div {
-///             "{number}"
-///         }
-///     }
-/// };
-/// ```
-///
-/// ## Raw Expressions
-///
-/// You can include raw expressions inside your markup inside curly braces. Your expression must implement the [`IntoDynNode`](https://docs.rs/dioxus-core/latest/dioxus_core/trait.IntoDynNode.html) trait:
-///
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// let name = "World";
-/// rsx! {
-///     div {
-///         // Text can be converted into a dynamic node in rsx
-///         {name}
-///     }
-///     // Iterators can also be converted into dynamic nodes
-///     {(0..10).map(|n| n * n).map(|number| rsx! { div { "{number}" } })}
-/// };
-/// ```
+#[doc = include_str!("../docs/rsx.md")]
 #[proc_macro]
 pub fn rsx(tokens: TokenStream) -> TokenStream {
     match syn::parse::<rsx::CallBody>(tokens) {
@@ -231,45 +54,7 @@ pub fn render(tokens: TokenStream) -> TokenStream {
     rsx(tokens)
 }
 
-/// Streamlines component creation.
-/// This is the recommended way of creating components,
-/// though you might want lower-level control with more advanced uses.
-///
-/// # Arguments
-/// * `no_case_check` - Doesn't enforce `PascalCase` on your component names.
-/// **This will be removed/deprecated in a future update in favor of a more complete Clippy-backed linting system.**
-/// The reasoning behind this is that Clippy allows more robust and powerful lints, whereas
-/// macros are extremely limited.
-///
-/// # Features
-/// This attribute:
-/// * Enforces that your component uses `PascalCase`.
-/// No warnings are generated for the `PascalCase`
-/// function name, but everything else will still raise a warning if it's incorrectly `PascalCase`.
-/// Does not disable warnings anywhere else, so if you, for example,
-/// accidentally don't use `snake_case`
-/// for a variable name in the function, the compiler will still warn you.
-/// * Automatically uses `#[inline_props]` if there's more than 1 parameter in the function.
-/// * Verifies the validity of your component.
-///
-/// # Examples
-/// * Without props:
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// #[component]
-/// fn GreetBob() -> Element {
-///     rsx! { "hello, bob" }
-/// }
-/// ```
-///
-/// * With props:
-/// ```rust, no_run
-/// # use dioxus::prelude::*;
-/// #[component]
-/// fn GreetBob(bob: String) -> Element {
-///    rsx! { "hello, {bob}" }
-/// }
-/// ```
+#[doc = include_str!("../docs/component.md")]
 #[proc_macro_attribute]
 pub fn component(_args: TokenStream, input: TokenStream) -> TokenStream {
     parse_macro_input!(input as ComponentBody)

+ 1 - 1
packages/core/src/global_context.rs

@@ -270,7 +270,7 @@ pub fn schedule_update_any() -> Arc<dyn Fn(ScopeId) + Send + Sync> {
 
 /// Creates a callback that will be run before the component is removed.
 /// This can be used to clean up side effects from the component
-/// (created with [`use_effect`](crate::use_effect)).
+/// (created with [`use_effect`](dioxus::prelude::use_effect)).
 ///
 /// Example:
 /// ```rust

+ 1 - 1
packages/core/src/scope_context.rs

@@ -438,7 +438,7 @@ impl ScopeId {
 
     /// Create a subscription that schedules a future render for the reference component. Unlike [`Self::needs_update`], this function will work outside of the dioxus runtime.
     ///
-    /// ## Notice: you should prefer using [`schedule_update_any`]
+    /// ## Notice: you should prefer using [`crate::prelude::schedule_update_any`]
     pub fn schedule_update(&self) -> Arc<dyn Fn() + Send + Sync + 'static> {
         Runtime::with_scope(*self, |cx| cx.schedule_update()).expect("to be in a dioxus runtime")
     }

+ 1 - 1
packages/dioxus/src/lib.rs

@@ -12,7 +12,7 @@
 //! - `router`: exports the [router](https://dioxuslabs.com/learn/0.5/router) and enables any router features for the current platform
 //! - `third-party-renderer`: Just disables warnings about no active platform when no renderers are enabled
 //!
-//! Platform features (the current platform determines what platform the [`launch`](dioxus::prelude::launch) function runs):
+//! Platform features (the current platform determines what platform the [`launch()`] function runs):
 //!
 //! - `fullstack`: enables the fullstack platform. This must be used in combination with the `web` feature for wasm builds and `axum` feature for server builds
 //! - `desktop`: enables the desktop platform

+ 1 - 1
packages/rsx/src/sub_templates.rs

@@ -42,4 +42,4 @@
 //! /// }
 //! ///
 //! /// We only track this when the template changes
-//! pub discovered_templates: Vec<Template>,
+//! pub discovered_templates: Vec<crate::Template>,