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 { None }
//! ```
//!
//! 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!"
//!             }
//!         }
//!     }
//! )
//! # };
//! ```