1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
//! # UI
//!
//! Freya uses a declarive model for the UI, which means that you do not use imperative APIs but instead you write in a semi-markup language (integrated with Rust) by using the `rsx!()` macro from Dioxus.
//!
//! For example, this is how a simple component would look like in Freya:
//!
//! ```rust, no_run
//! # use freya::prelude::*;
//! fn app() -> Element {
//!     rsx!(
//!         rect {
//!             background: "red",
//!             width: "100%",
//!             onclick: |_| println!("Clicked!"),
//!             label {
//!                 "Hello, World!"
//!             }
//!         }
//!     )
//! }
//! ```
//!
//! Notice that the `app` component is returning an [`Element`](dioxus_core::Element) created by the [`rsx!()`](dioxus_core_macro::rsx!()) macro. So, in other words, the [`Element`](dioxus_core::Element) contains the UI of that component.
//! Every time the component reruns the [`rsx!()`](dioxus_core_macro::rsx!()) will be called again and thus generate a new UI.
//!
//! ### [`rsx!()`](dioxus_core_macro::rsx!())
//!
//! This macro is not a standalone-language or anything like that. It is simply a macro to easily declare how we want the UI to look like. You can still use normal Rust code inside.
//!
//! The structure for RSX looks like this:
//!
//! ```rust, no_run
//! # use freya::prelude::*;
//! # { rsx!(
//! // Element, always in lower case
//! rect {
//!     // Attribute for the element `rect`
//!     background: "red",
//!     // Attribute for the element `rect`
//!     width: "100%",
//!     // Event handler for the element `rect`, can be a function or a closure
//!     onclick: |_| println!("Clicked!"),
//!     // Element child of `rect`
//!     label {
//!         // Text Element for the element `label`
//!         "Hello, World!"
//!     }
//!     // Component child of `rect`, always in PascalCase
//!     CoolComp {
//!         // Prop for the component `CoolComp`
//!         prop: 123
//!     }
//! }
//! # )};
//!
//! # #[component]
//! # fn CoolComp(prop: i32) -> Element { Ok(VNode::placeholder()) }
//! ```
//!
//! You can reference variables inside the RSX as well:
//!
//! ```rust, no_run
//! # use freya::prelude::*;
//! let onclick = |_| {
//!     println!("Clicked");
//! };
//!
//! let width = "100%";
//! let name = "World";
//!
//! # {
//! rsx!(
//!     rect {
//!         background: "red",
//!         width,
//!         onclick,
//!         label {
//!             "Hello, {name}!"
//!         }
//!         label {
//!         "{1 + 1} is 2"
//!         }
//!     }
//! )
//! # };
//! ```
//!
//! Or just use if, for-loops, etc... inside of the RSX:
//!
//! ```rust, no_run
//! # use freya::prelude::*;
//! let show_text = false;
//!
//! # {
//! rsx!(
//!     rect {
//!         for i in 0..5 {
//!             label {
//!             // Looped elements must have an unique ID specified through
//!                 // the `key` attribute so Dioxus is able to identify them
//!                 key: "{i}",
//!                 "Value -> {i}"
//!             }
//!         }
//!         // When this condition is not met the inner element will simply not be rendered
//!         if show_text {
//!             label {
//!                 "Hello, World!"
//!             }
//!         }
//!     }
//! )
//! # };
//! ```