From fcc9eaf48d910e4f5b1facd3c7cdb18b1ae3192b Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sat, 6 Apr 2024 13:29:02 +0200 Subject: [PATCH] feat: Revamped book --- book/src/SUMMARY.md | 23 +- book/src/differences_with_dioxus.md | 2 +- book/src/getting_started.md | 99 ++++++ book/src/guides/animating.md | 91 ----- book/src/guides/components.md | 3 - book/src/guides/devtools.md | 3 +- book/src/guides/dioxus.md | 185 +++++++++++ book/src/guides/effects.md | 25 -- book/src/guides/elements.md | 104 ------ book/src/guides/font_style.md | 422 ------------------------ book/src/guides/getting_started.md | 72 ---- book/src/guides/hot_reload.md | 20 -- book/src/guides/layout.md | 224 ------------- book/src/guides/style.md | 165 --------- book/src/guides/testing.md | 151 --------- book/src/guides/theming.md | 123 ------- book/src/guides/virtual_scroll_view.png | Bin 14708 -> 0 bytes book/src/guides/virtualizing.md | 75 ----- book/src/index.md | 81 +++-- book/src/setup.md | 2 +- book/src/what_is_freya.md | 26 -- 21 files changed, 346 insertions(+), 1550 deletions(-) create mode 100644 book/src/getting_started.md delete mode 100644 book/src/guides/animating.md delete mode 100644 book/src/guides/components.md create mode 100644 book/src/guides/dioxus.md delete mode 100644 book/src/guides/effects.md delete mode 100644 book/src/guides/elements.md delete mode 100644 book/src/guides/font_style.md delete mode 100644 book/src/guides/getting_started.md delete mode 100644 book/src/guides/hot_reload.md delete mode 100644 book/src/guides/layout.md delete mode 100644 book/src/guides/style.md delete mode 100644 book/src/guides/testing.md delete mode 100644 book/src/guides/theming.md delete mode 100644 book/src/guides/virtual_scroll_view.png delete mode 100644 book/src/guides/virtualizing.md delete mode 100644 book/src/what_is_freya.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index d902cd26a..ec2efee83 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -2,24 +2,15 @@ # Introduction -- [Welcome](./index.md) -- [What is Freya?](./what_is_freya.md) +- [Overview](./index.md) +- [Setup](setup.md) +- [Getting Started](./getting_started.md) + +# Other - [Differences with Dioxus](differences_with_dioxus.md) -- [Environment Setup](setup.md) -- [Getting started](./guides/getting_started.md) -- [Frequently Asked Questions](./faq.md) +- [FAQ](./faq.md) # Guides -- [Elements](./guides/elements.md) -- [Layout](./guides/layout.md) -- [Style](./guides/style.md) -- [Font Style](./guides/font_style.md) -- [Effects](./guides/effects.md) -- [Components](./guides/components.md) -- [Theming](./guides/theming.md) -- [Hot reload](./guides/hot_reload.md) -- [Testing](./guides/testing.md) -- [Animating](./guides/animating.md) -- [Virtualizing](./guides/virtualizing.md) +- [Learn Dioxus](./guides/dioxus.md) - [Devtools](./guides/devtools.md) - [Publishing](./guides/publishing.md) diff --git a/book/src/differences_with_dioxus.md b/book/src/differences_with_dioxus.md index 8ad385ed5..a3854b4ed 100644 --- a/book/src/differences_with_dioxus.md +++ b/book/src/differences_with_dioxus.md @@ -1,6 +1,6 @@ # Differences with Dioxus -**Freya** uses most of the core packages of Dioxus, but not all them. +**Freya** uses some of the core packages of Dioxus, but not all them. These are the main differences between Freya and the official Dioxus renderers for Desktop (webview and Blitz): diff --git a/book/src/getting_started.md b/book/src/getting_started.md new file mode 100644 index 000000000..2b27027e5 --- /dev/null +++ b/book/src/getting_started.md @@ -0,0 +1,99 @@ +# Getting Started + +I encourage you to learn how [Dioxus works](https://dioxuslabs.com/learn/0.5/guide/your_first_component), when you are done you can continue here. Also make sure you have the followed the [environment setup](../setup.html) guide. + +Now, let's start by creating a hello world project. + +### Creating the project + +```sh +mkdir freya-app +cd freya-app +cargo init +``` + +### Cargo.toml + +Make sure to add Freya and Dioxus as dependencies: + +```toml +[package] +name = "freya-app" +version = "0.1.0" +edition = "2021" + +[dependencies] +freya = "0.2" +dioxus = { version = "0.5", features = ["macro", "hooks"], default-features = false } +``` + +### src/main.rs + +In Freya, your run your app by calling a `launch` method and passing your root Component: + +```rust, no_run +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +use freya::prelude::*; + +fn main() { + launch(app); // This will block the main thread +} +``` + +Let's define our root component, called `app`: + +```rust, no_run +fn app() -> Element { + render!( + label { "Hello, World!" } + ) +} +``` + +Components in Freya/Dioxus are simply functions that return an `Element`. + +Let's make it stateful by using Dioxus Signals: + +```rust, no_run +fn app() -> Element { + // `use_signal` takes a callback that initializes the state + let mut state = use_signal(|| 0); + + // Because signals are copy, we can move them into closures + let onclick = move |_| { + // Signals provide some shortcuts for certain types + state += 1; + // But we could do as well + *state.write() += 1; + }; + + // You can subscribe to a signal, by calling it (`signal()`), + // calling the `signal.read()` method, or just embedding it into the RSX. + // and thus producing a new Element with the updated counter. + // So, everytime the signal is mutated the component function will rerun + // because it has been subscribed + println!("{}", state()); + + render!( + label { + onclick, + "State is {state}" + } + ) +} +``` + +### Running +Simply run with `cargo`: + +```sh +cargo run +``` + +Nice! You have created your first Freya app. + +You can learn more with the [examples](https://github.com/marc2332/freya/tree/main/examples) in the repository. \ No newline at end of file diff --git a/book/src/guides/animating.md b/book/src/guides/animating.md deleted file mode 100644 index 9afdf8808..000000000 --- a/book/src/guides/animating.md +++ /dev/null @@ -1,91 +0,0 @@ -# Animating - -Freya provides you with two hooks to help you animate your components. - -### `use_animation` - -This a very simple hook that will let you animate a certain value from an `inital` value to a `final` value, in a given `duration` of time. There are a few animations that you can choose from: - -- Linear -- EaseIn -- EaseInOut -- BounceIns - -Here is an example that will animate a value from `0.0` to `100.0` in `50` milliseconds, using the `linear` animation. - -```rust, no_run -fn main() { - launch(app); -} - - fn app(cx: Scope) -> Element { - let animation = use_animation(cx, || 0.0); - - let progress = animation.value(); - - use_memo(cx, (), move |_| { - animation.start(Animation::new_linear(0.0..=100.0, 50)); - }); - - render!(rect { - width: "{progress}", - }) -} -``` - -### `use_animation_transition` - -This hook let's you group a set of animations together with a certain type of `animation` and a given `duration`. You can also specifiy a set of dependencies that will make animations callback re run. - -Just like `use_animation` you have these animations: - -- Linear -- EaseIn -- EaseInOut -- BounceIns - -Here is an example that will animate a `size` and a color in `200` milliseconds, using the `new_sine_in_out` animation. - -```rust, no_run -fn main() { - launch(app); -} - -const TARGET: f64 = 500.0; - -fn app(cx: Scope) -> Element { - let animation = use_animation_transition(cx, TransitionAnimation::new_sine_in_out(200), (), || { - vec![ - Animate::new_size(0.0, TARGET), - Animate::new_color("rgb(33, 158, 188)", "white"), - ] - }); - - let size = animation.get(0).unwrap().as_size(); - let background = animation.get(1).unwrap().as_color(); - - let onclick = move |_: MouseEvent| { - if size == 0.0 { - animation.start(); - } else if size == TARGET { - animation.reverse(); - } - }; - - render!( - rect { - overflow: "clip", - background: "black", - width: "100%", - height: "100%", - offset_x: "{size}", - rect { - height: "100%", - width: "200", - background: "{background}", - onclick: onclick, - } - } - ) -} -``` diff --git a/book/src/guides/components.md b/book/src/guides/components.md deleted file mode 100644 index b1f8d267d..000000000 --- a/book/src/guides/components.md +++ /dev/null @@ -1,3 +0,0 @@ -# Components - -Freya comes with a set of ready to use components. View the [API docs](https://docs.rs/freya/latest/freya/components/index.html#functions) for a full list. diff --git a/book/src/guides/devtools.md b/book/src/guides/devtools.md index 140a5501b..5fabe04e0 100644 --- a/book/src/guides/devtools.md +++ b/book/src/guides/devtools.md @@ -2,12 +2,11 @@ Devtools can be enabled by adding the `devtools` to Freya. - ```toml // Cargo.toml [dependencies] -freya = { version = "0.1", features = ["devtools"] } +freya = { version = "0.2", features = ["devtools"] } ``` diff --git a/book/src/guides/dioxus.md b/book/src/guides/dioxus.md new file mode 100644 index 000000000..5081562c4 --- /dev/null +++ b/book/src/guides/dioxus.md @@ -0,0 +1,185 @@ +# Learn Dioxus + +This is a quick introduction to Dioxus in the world of Freya. For more examples or tips you can check the official [Dioxus Docs](https://dioxuslabs.com/learn/0.5/) or the [Dioxus Cheatsheet](https://github.com/marc2332/dioxus-cheatsheet) + +## Components +Components in Dioxus are defined in the form of funtions that might receive some `props` and return an `Element`. + +The Element is generated by the `rsx!()` macro. + +```rs, no_run +fn MyComponent() -> Element { + rsx!(...) +} +``` + +## RSX + +Dioxus uses a custom markdup syntax called RSX, it's conceptually similar to React's JSX. + +Syntax: + +```rs + { + : , + +} +``` + +Example: + +```rs, no_run +rsx!( + label { + onclick: |_| println!("Clicked"), + color: "red", + font_size: "50", + "Hello, World!" + } +) +``` + +Another Example: + +```rs, no_run +rsx!( + rect { + color: "red", + onclick: |_| println!("Clicked rect"), + label { + onclick: |_| println!("Clicked label"), + font_size: "50", + "Hello, World!" + } + AnotherComponent { + some_value: 123 + } + } +) +``` + +## Props + +Use the `component` macro if you want to have inlined props: + +```rs, no_run +#[component] +fn MyComponent(name: String, age: u8) -> Element { + rsx!( + label { + "{name} is {age} years old." + } + ) +} +``` + +You can as well have a separate Struct for the props: +```rs, no_run + +struct MyComponentProps { + name: String, + age: u8 +} + +fn MyComponent(props: MyComponentProps) -> Element { + rsx!( + label { + "{props.name} is {props.age} years old." + } + ) +} +``` + + +## State + +Dioxus built-in state management uses **Signals**, and they are usually created with the `use_signal` hook. + +```rs, no_run +fn MyComponent() -> Element { + // `use_signal` takes a callback that initializes the state + let mut state = use_signal(|| 0); + + // Because signals are copy, we can move them into closures + let onclick = move |_| { + // Signals provide some shortcuts for certain types + state += 1; + // But we could do as well + *state.write() += 1; + }; + + // You can subscribe to a signal, by calling it (`signal()`), + // calling the `signal.read()` method, or just embedding it into the RSX. + // and thus producing a new Element with the updated counter. + // So, everytime the signal is mutated the component function will rerun + // because it has been subscribed + println!("{}", state()); + + rsx!( + label { + onclick, + "State is {value}" + } + ) +} +``` + +## Shared State + +Signals can be passed to other components so they can read/write to the same signal. + + +```rs, no_run +fn app() -> Element { + let state = use_signal(|| 0); + + // We pass the signal through the context API + // So `ThirdComponent` can consume + use_context_provider(|| state); + + rsx!( + SecondComponent { + state // We can pass the signal as a prop as well + } + ThirdComponent {} + ) +} + +#[component] +fn SecondComponent(mut state: Signal) -> Element { + let onclick = move |_| { + state += 1; + }; + + rsx!( + label { + onclick, + "Second component: {state}" + } + ) +} + +#[component] +fn ThirdComponent() -> Element { + // We consume the signal passed through `use_context_provider` + let mut state = use_context::>(); + + let onclick = move |_| { + state += 1; + }; + + rsx!( + label { + onclick, + "Third component: {state}" + } + ) +} +``` + +## Alternative State Management + +There are other state management libraries with more granular control or with other goals that are worth checking out. + +- [`dioxus-radio`](https://github.com/dioxus-community/dioxus-radio) +- [`dioxus-query`](https://github.com/marc2332/dioxus-query) \ No newline at end of file diff --git a/book/src/guides/effects.md b/book/src/guides/effects.md deleted file mode 100644 index 494fba317..000000000 --- a/book/src/guides/effects.md +++ /dev/null @@ -1,25 +0,0 @@ -# Effects - -Learn how the effects attributes work. - -- [`rotate`](#rotate) - -### rotate - -The `rotate` attribute let's you rotate an element. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - rotate: "180deg", - "Hello, World!" - } - ) -} -``` - - -Compatible elements: all except [`text`](/guides/elements.html#paragraph-and-text). \ No newline at end of file diff --git a/book/src/guides/elements.md b/book/src/guides/elements.md deleted file mode 100644 index eb7afd058..000000000 --- a/book/src/guides/elements.md +++ /dev/null @@ -1,104 +0,0 @@ -# Elements - -Freya contains a set of primitive elements: - -- [`rect`](#rect) -- [`label`](#label) -- [`image`](#image) -- [`svg`](#svg) -- [`paragraph and text`](#paragraph-and-text-and-text) - -## rect - -The `rect` element (aka `rectangle`) is a box where you can place as many elements inside you want. -You can specify things like [`width`](/guides/layout.html#width), [`paddings`](/guides/layout.html#padding) or even in what [`direction`](/guides/layout.html#direction) the inner elements are stacked. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - direction: "vertical", - label { "Hi!" } - label { "Hi again!"} - } - ) -} -``` - -### label - -The `label` element simply shows some text. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - "Hello World" - } - ) -} -``` - -### svg - -The `svg` element let's you draw a SVG. You will need to use the `bytes_to_data` to transform the bytes into data the element can recognize. - -Example: - -```rust, no_run - -static FERRIS: &[u8] = include_bytes!("./ferris.svg"); - -fn app(cx: Scope) -> Element { - let ferris = bytes_to_data(cx, FERRIS); - render!( - svg { - svg_data: ferris, - } - ) -} -``` - -### image - -The `image` element, just like `svg` element, require you to pass the image bytes yourself. - -```rust, no_run -static RUST_LOGO: &[u8] = include_bytes!("./rust_logo.png"); - -fn app(cx: Scope) -> Element { - let image_data = bytes_to_data(cx, RUST_LOGO); - render!( - image { - image_data: image_data, - width: "{size}", - height: "{size}", - } - ) -} -``` - -### paragraph and text - -Both `paragraph` and `text` elements are used together. They will let you build texts with different styles. - -``` rust -fn app(cx: Scope) -> Element { - render!( - paragraph { - text { - font_size: "15", - "Hello, " - } - text { - font_size: "30", - "World!" - } - } - ) -} -``` diff --git a/book/src/guides/font_style.md b/book/src/guides/font_style.md deleted file mode 100644 index 6c027245b..000000000 --- a/book/src/guides/font_style.md +++ /dev/null @@ -1,422 +0,0 @@ -# Font Style - -Learn how the font style attributes work. - -- [`color`](#color) -- [`font_family`](#font_family) -- [`font_size`](#font_size) -- [`align`](#align) -- [`font_style`](#font_style) -- [`font_weight`](#font_weight) -- [`font_width`](#font_width) -- [`line_height`](#line_height) -- [`max_lines`](#max_lines) -- [`letter_spacing`](#letter_spacing) -- [`word_spacing`](#word_spacing) -- [`decoration`](#decoration) -- [`decoration_style`](#decoration_style) -- [`decoration_color`](#decoration_color) -- [`text_shadow`](#text_shadow) -- [`text_overflow`](#text_overflow) - - -### color - -The `color` attribute let's you specify the color of the text. - -You can learn about the syntax of this attribute in [`Color Syntax`](/guides/style.html#color-syntax). - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - color: "green", - "Hello, World!" - } - ) -} -``` - -Another example showing [inheritance](#inheritance): - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - color: "blue", - label { - "Hello, World!" - } - } - ) -} - -``` - -Compatible elements: [`label`](/guides/elements.html#label), [`paragraph`](/guides/elements.html#paragraph-and-text), [`text`](/guides/elements.html#paragraph-and-text) - -### font_family - -With the `font_family` you can specify what font do you want to use for the inner text. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - font_family: "Inter", - "Hello, World!" - } - ) -} -``` - -You can also specify multiple fonts in order of priority, if one is not found it will fallback to the next one. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - font_family: "DoesntExist Font, Impact", - "Hello, World!" - } - ) -} -``` - -Compatible elements: [`label`](/guides/elements.html#label), [`paragraph`](/guides/elements.html#paragraph-and-text), - -### font_size - -You can specify the size of the text using `font_size`. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - font_size: "50", - "Hellooooo!" - } - ) -} -``` - -Compatible elements: [`label`](/guides/elements.html#label), [`paragraph`](/guides/elements.html#paragraph-and-text), [`text`](/guides/elements.html#paragraph-and-text) - -### align - -You can change the alignment of the text using the `align` attribute. - -Accepted values: `center`, `end`, `justify`, `left`, `right`, `start` - -Example - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - align: "right", - "Hello, World!" - } - ) -} -``` - -Compatible elements: [`label`](/guides/elements.html#label), [`paragraph`](/guides/elements.html#paragraph-and-text), - -### font_style - -You can choose a style for a text using the `font_style` attribute. - -Accepted values: `upright` (default), `italic` and `oblique`. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - font_style: "italic", - "Hello, World!" - } - ) -} -``` - -Compatible elements: [`text`](/guides/elements.html#paragraph-and-text), [`label`](/guides/elements.html#label). - -### font_weight - -You can choose a weight for a text using the `font_weight` attribute. - -Accepted values: -- `invisible` -- `thin` -- `extra-light` -- `light` -- `normal` (default) -- `medium` -- `semi-bold` -- `bold` -- `extra-bold` -- `black` -- `extra-black` -- `50` -- `100` -- `200` -- `300` -- `400` -- `500` -- `600` -- `700` -- `800` -- `900` -- `950` - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - font_weight: "bold", - "Hello, World!" - } - ) -} -``` - -Compatible elements: [`text`](/guides/elements.html#paragraph-and-text), [`label`](/guides/elements.html#label). - -### font_width - -You can choose a width for a text using the `font_width` attribute. - -Accepted values: -- `ultra-condensed` -- `extra-condensed` -- `condensed` -- `normal` (default) -- `semi-expanded` -- `expanded` -- `extra-expanded` -- `ultra-expanded` - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - font_weight: "bold", - "Hello, World!" - } - ) -} -``` - - -Compatible elements: [`text`](/guides/elements.html#paragraph-and-text), [`label`](/guides/elements.html#label). - - -### line_height - -Specify the height of the lines of the text. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - lines_height: "3", - "Hello, World! \n Hello, again!" - } - ) -} -``` - -### max_lines - -Determines the amount of lines that the text can have. It has unlimited lines by default. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - "Hello, World! \n Hello, World! \n Hello, world!" // Will show all three lines - } - label { - max_lines: "2", - "Hello, World! \n Hello, World! \n Hello, world!" // Will only show two lines - } - ) -} -``` - -Compatible elements: [`text`](/guides/elements.html#paragraph-and-text), [`paragraph`](/guides/elements.html#paragraph-and-text). - -### letter_spacing - -Specify the spacing between characters of the text. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - letter_spacing: "10", - "Hello, World!" - } - ) -} -``` - -Compatible elements: [`text`](/guides/elements.html#paragraph-and-text), [`paragraph`](/guides/elements.html#paragraph-and-text), [`label`](/guides/elements.html#label). - -### word_spacing - -Specify the spacing between words of the text. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - word_spacing: "10", - "Hello, World!" - } - ) -} -``` - -Compatible elements: [`text`](/guides/elements.html#paragraph-and-text), [`paragraph`](/guides/elements.html#paragraph-and-text), [`label`](/guides/elements.html#label). - -### decoration - -Specify the decoration in a text. - -Accpted values: -- `underline` -- `line-through` -- `overline` - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - decoration: "line-through", - "Hello, World!" - } - ) -} -``` - -Compatible elements: [`text`](/guides/elements.html#paragraph-and-text), [`paragraph`](/guides/elements.html#paragraph-and-text), [`label`](/guides/elements.html#label). - -### decoration_style - -Specify the decoration's style in a text. - -Accpted values: -- `solid` (default) -- `double` -- `dotted` -- `dashed` -- `wavy` - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - decoration: "line-through", - decoration_style: "dotted", - "Hello, World!" - } - ) -} -``` - -Compatible elements: [`text`](/guides/elements.html#paragraph-and-text), [`paragraph`](/guides/elements.html#paragraph-and-text), [`label`](/guides/elements.html#label). - -### decoration_color - -Specify the decoration's color in a text. - -You can learn about the syntax of this attribute in [`Color Syntax`](/guides/style.html#color-syntax). - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - decoration: "line-through", - decoration_color: "orange", - "Hello, World!" - } - ) -} -``` - -Compatible elements: [`text`](/guides/elements.html#paragraph-and-text), [`paragraph`](/guides/elements.html#paragraph-and-text), [`label`](/guides/elements.html#label). - -### text_shadow - -Specify the shadow of a text. - -Syntax: ` ` - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - text_shadow: "0 18 12 rgb(0, 0, 0)", - "Hello, World!" - } - ) -} -``` - -Compatible elements: [`text`](/guides/elements.html#paragraph-and-text), [`label`](/guides/elements.html#label). - -### text_overflow - -Determines how text is treated when it exceeds its [`max_lines`](#max_lines) count. By default uses the `clip` mode, which will cut off any overflowing text, with `ellipsis` mode it will show `...` at the end. - -Accepted values: -- `clip` (default) -- `ellipsis` - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - label { - max_lines: "3", - text_overflow: "ellipsis", - "Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong text" - } - ) -} -``` - -Compatible elements: [`label`](/guides/elements.html#label), [`paragraph`](/guides/elements.html#paragraph-and-text). diff --git a/book/src/guides/getting_started.md b/book/src/guides/getting_started.md deleted file mode 100644 index 3ce82c631..000000000 --- a/book/src/guides/getting_started.md +++ /dev/null @@ -1,72 +0,0 @@ -# Getting started - -I encourage you to learn how [Dioxus works](https://dioxuslabs.com/learn/0.4/guide/your_first_component), when you are done you can continue here. Also make sure you have the followed the [environment setup](../setup.html) guide. - -Now, let's start by creating a hello world project. - -### Creating the project - -```sh -mkdir freya-app -cd freya-app -cargo init -``` - -### Cargo.toml - -Make sure to add Freya and Dioxus as dependencies: - -```toml -[package] -name = "freya-app" -version = "0.1.0" -edition = "2021" - -[dependencies] -freya = "0.1" -dioxus = { version = "0.4", features = ["macro", "hooks"], default-features = false } -``` - -### src/main.rs - -And paste this code in your `main.rs` file. - -```rust, no_run no_run -#![cfg_attr( - all(not(debug_assertions), target_os = "windows"), - windows_subsystem = "windows" -)] - -use freya::prelude::*; - -fn main() { - launch(app); -} - -fn app(cx: Scope) -> Element { - let mut count = use_state(cx, || 0); - - render!( - rect { - height: "100%", - width: "100%", - background: "rgb(35, 35, 35)", - color: "white", - padding: "12", - onclick: move |_| count += 1, - label { "Click to increase -> {count}" } - } - ) -} -``` - -### Running -Simply run with `cargo`: - -```sh -cargo run -``` - -Nice! You have created your first Freya app. - -You can learn more with the [examples](https://github.com/marc2332/freya/tree/main/examples) in the repository. \ No newline at end of file diff --git a/book/src/guides/hot_reload.md b/book/src/guides/hot_reload.md deleted file mode 100644 index 1d61f57dc..000000000 --- a/book/src/guides/hot_reload.md +++ /dev/null @@ -1,20 +0,0 @@ -# Hot reload - -Freya supports Dioxus hot reload, which means that you can update the `layout` and `styling` of your app on the fly, without having to recompile your project. - -## Setup - -Before launching your app, you need to initialize the hot-reload context: - -```rust, no_run -use freya::prelude::*; -use freya::hotreload::FreyaCtx; - -fn main() { - dioxus_hot_reload::hot_reload_init!(Config::::default()); - - launch(app); -} -``` - -That's it! diff --git a/book/src/guides/layout.md b/book/src/guides/layout.md deleted file mode 100644 index ea49c7752..000000000 --- a/book/src/guides/layout.md +++ /dev/null @@ -1,224 +0,0 @@ -# Layout - -Learn how the layout attributes work. - -- [`width & height`](#width--height) -- [`min_width & min_height`](#min_width--min_height) -- [`max_width & max_height`](#max_width--max_height) -- [`Size units`](#size_units) - - [`Logical pixels`](#logical-pixels) - - [`Percentages`](#percentages) - - [`calc()`](#calc) -- [`direction`](#direction) -- [`padding`](#padding) -- [`margin`](#margin) -- [`display`](#display) - -> ⚠️ Freya's layout is still somewhat limited. - -### width & height -All elements support both `width` and `height` attributes. - -See syntax for [`Size Units`](#size-units). - -##### Usage - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - background: "red", - width: "15", - height: "50", - } - ) -} -``` - -### min_width & min_height - -`rect` supports specifying a minimum width and height, this can be useful if you use it alongside a percentage for the target size. - -See syntax for [`Size Units`](#size-units). - -##### Usage - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - background: "red", - min_width: "100", - min_height: "100", - width: "50%", - height: "50%", - } - ) -} -``` - -### max_width & max_height - -`rect` supports specifying a maximum width and height. - -See syntax for [`Size Units`](#size-units). - -##### Usage - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - background: "red", - max_width: "50%", - max_height: "50%", - width: "500", - height: "500", - } - ) -} -``` - -### Size Units - -#### Auto -Will use it's inner children as size, so in this case, the `rect` width will be equivalent to the width of `label`: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - width: "auto", - height: "33", - label { - "hello!" - } - } - ) -} -``` - -#### Logical pixels - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - width: "50", - height: "33" - } - ) -} -``` - -#### Percentages -Relative percentage to the parent equivalent value. - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - width: "50%", // Half the parent - height: "75%" // 3/4 the parent - } - ) -} -``` - -#### `calc()` - -For more complex logic you can use the `calc()` function. - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - width: "calc(33% - 60 + 15%)", // (1/3 of the parent minus 60) plus 15% of parent - height: "calc(100% - 10)" // 100% of the parent minus 10 - } - ) -} -``` - -### direction - -Control how the inner elements will be stacked, possible values are `horizontal`, `vertical` (default) or `both` (default for text elements, e.g label, paragraph, text, etc). - -##### Usage - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - width: "100%", - height: "100%", - direction: "vertical", - rect { - width: "100%", - height: "50%", - background: "red" - }, - rect { - width: "100%", - height: "50%", - background: "green" - } - } - ) -} -``` - -### padding - -Specify the inner paddings of an element. You can do so by three different ways. - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - padding: "25" // 25 in all sides - padding: "100 50" // 100 in top and bottom, and 50 in left and right - padding: "5 7 3 9" // 5 in top, 7 in right, 3 in bottom and 9 in left - } - ) -} - -``` - -### display - -Control how the inner elements are displayed, possible values are `normal` (default) or `center`. - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - width: "100%", - height: "100%", - direction: "both", - display: "center", - rect { - width: "50%", - height: "50%", - background: "red" - }, - } - ) -} -``` - -### margin - -Specify the margin of an element. You can do so by three different ways. - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - margin: "25" // 25 in all sides - margin: "100 50" // 100 in top and bottom, and 50 in left and right - margin: "5 7 3 9" // 5 in top, 7 in right, 3 in bottom and 9 in left - } - ) -} -``` \ No newline at end of file diff --git a/book/src/guides/style.md b/book/src/guides/style.md deleted file mode 100644 index 2053e54de..000000000 --- a/book/src/guides/style.md +++ /dev/null @@ -1,165 +0,0 @@ -# Style - -Learn how the style attributes work. - -- [`background`](#background) -- [`shadow`](#shadow) -- [`corner radius & corner smoothing`](#corner_radius--corner_smoothing) -- [`border`](#border) -- [`overflow`](#overflow) -- [`Color syntax`](#color-syntax) - - [`Static colors`](#static-colors) - - [`rgb() / hsl(`)](#rgb--hsl) -- [`Inheritance`](#inheritance) - -### background - -The `background` attribute will let you specify a color as the background of the element. - -You can learn about the syntax of this attribute [here](#color-syntax). - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - background: "red" - } - ) -} -``` - -Compatible elements: [`rect`](/guides/elements.html#rect) - - -### shadow - -The `shadow` attribute let's you draw a shadow outside of the element. - -Syntax: ` ` - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - shadow: "0 0 25 2 rgb(0, 0, 0, 120)" - } - ) -} -``` - -Compatible elements: [`rect`](/guides/elements.html#rect) - -### corner_radius & corner_smoothing - -The `corner_radius` attribute let's you smooth the corners of the element, with `corner_smoothing` you can archieve a "squircle" effect. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - corner_radius: "10", - corner_smoothing: "75%" - } - ) -} -``` - -Compatible elements: [`rect`](/guides/elements.html#rect) - -### border - -You can add a border to an element using the `border` and `border_align` attributes. - -- `border` syntax: `[width] [color]`. -- `border_align` syntax: ``. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - border: "2 solid black", - border_align: "inner" - } - ) -} -``` - -Compatible elements: [`rect`](/guides/elements.html#rect) - -### overflow - -Specify how overflow should be handled. - -Accepted values: `clip | none`. - -Example: - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - rect { - overflow: "clip" - width: "100", - height: "100%", - rect { - width: "500", - height: "100%", - background: "red", - } - } - ) -} -``` - -Compatible elements: [`rect`](/guides/elements.html#rect) - -### Color syntax - -The attributes that have colors as values can use the following syntax: - -#### Static colors -- `red` -- `blue` -- `green` -- `yellow` -- `black` (default for `color` attribute) -- `gray` -- `white` (default for `background` attribute) -- `orange` -- `transparent` - -#### rgb() / hsl() - -- With RGB: `rgb(150, 60, 20)` -- With RGB and alpha: `rgb(150, 60, 20, 70)` -- With HSL: `hsl(28deg, 80%, 50%)` -- With HSL and alpha: `hsl(28deg, 80%, 50%, 25%)` - -### Inheritance - -These are some attribute that are inherited from the element parents: - -- `color` -- `font_family` -- `font_size` -- `font_style` -- `font_weight` -- `font_width` -- `line_height` -- `align` -- `max_lines` -- `letter_spacing` -- `word_spacing` -- `decoration` -- `decoration_style` -- `decoration_color` -- `text_shadow` - diff --git a/book/src/guides/testing.md b/book/src/guides/testing.md deleted file mode 100644 index 0cf151773..000000000 --- a/book/src/guides/testing.md +++ /dev/null @@ -1,151 +0,0 @@ -# Testing - -Freya comes with a special testing renderer (`freya-testing`) that let's you run your components in a headless environment. -This will let you easily write unit tests for your components. - -## Getting started - -You can use the `launch_test` function to run the tests of your component, it will return you a set of utilities for you to interact with the component. - -For example, this will launch a state-less component and assert that it renders a label with the text `"Hello World!"`. - -```rust, no_run -#[tokio::test] -async fn test() { - fn our_component(cx: Scope) -> Element { - render!( - label { - "Hello World!" - } - ) - } - - let mut utils = launch_test(our_component); - - let root = utils.root(); - let label = root.get(0); - let label_text = label.get(0); - - assert_eq!(label_text.text(), Some("Hello World!")); -} -``` - -The `root()` function will give you the Root node of your app, then, with the `get` function you can retrieve a Node from it's parent given it's index position. - -## Dynamic components - -If the component has logic that might execute asynchronously, you will need to wait for the component to update using the `wait_for_update` function before asserting the result. - -Here, the component has a state that is `false` by default, but, once mounted it will update the state to `true`. - -```rust, no_run -#[tokio::test] -async fn dynamic_test() { - fn dynamic_component(cx: Scope) -> Element { - let state = use_state(cx, || false); - - use_effect(cx, (), |_| { - state.set(true); - async move { } - }); - - render!( - label { - "Is enabled? {state}" - } - ) - } - - let mut utils = launch_test(dynamic_component); - - let root = utils.root(); - let label = root.get(0); - - assert_eq!(label.get(0).text(), Some("Is enabled? false")); - - // This will run the `use_effect` and update the state. - utils.wait_for_update().await; - - assert_eq!(label.get(0).text(), Some("Is enabled? true")); -} -``` - -## Events - -We can also simulate events on the component, for example, we can simulate a click event on a `rect` and assert that the state has been updated. - -```rust, no_run -#[tokio::test] -async fn event_test() { - fn event_component(cx: Scope) -> Element { - let enabled = use_state(cx, || false); - render!( - rect { - width: "100%", - height: "100%", - background: "red", - onclick: |_| { - enabled.set(true); - }, - label { - "Is enabled? {enabled}" - } - } - ) - } - - let mut utils = launch_test(event_component); - - let rect = utils.root().get(0); - let label = rect.get(0); - - utils.wait_for_update().await; - - let text = label.get(0); - assert_eq!(text.text(), Some("Is enabled? false")); - - // Push a click event to the events queue - utils.push_event(FreyaEvent::Mouse { - name: "click", - cursor: (5.0, 5.0).into(), - button: Some(MouseButton::Left), - }); - - // Run the queued events and update the state - utils.wait_for_update().await; - - // Because the click event was executed and the state updated, now the text has changed too! - let text = label.get(0); - assert_eq!(text.text(), Some("Is enabled? true")); -} -``` - -## Testing configuration - -The `launch_test` comes with a default configuration, but you can also pass your own config with the `launch_test_with_config` function. - -Here is an example of how to can set our custom window size: - -```rust, no_run -#[tokio::test] -async fn test() { - fn our_component(cx: Scope) -> Element { - render!( - label { - "Hello World!" - } - ) - } - - let mut utils = launch_test_with_config( - our_component, - *TestingConfig::default().with_size((500.0, 800.0).into()), - ); - - let root = utils.root(); - let label = root.get(0); - let label_text = label.get(0); - - assert_eq!(label_text.text(), Some("Hello World!")); -} -```` \ No newline at end of file diff --git a/book/src/guides/theming.md b/book/src/guides/theming.md deleted file mode 100644 index e192dc95f..000000000 --- a/book/src/guides/theming.md +++ /dev/null @@ -1,123 +0,0 @@ -# Theming - -Freya has built-in support for Theming. - -> ⚠️ Currently, extending the base theme is not supported. - -## Accessing the current theme - -You can access the whole current theme via the `use_get_theme` hook. - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - ThemeProvider { - Component { } - } - ) -} - -#[allow(non_snake_case)] -fn Component(cx: Scope) -> Element { - let theme = use_get_theme(cx); - - let button_theme = &theme.button; - - render!( - rect { - background: "{button_theme.background}", - } - ) -} -``` - -## Custom default theme -By default, the selected theme is `LIGHT_THEME`. You can use the alternative, `DARK_THEME`. - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - ThemeProvider { - theme: LIGHT_THEME, - Component { } - } - ) -} - -#[allow(non_snake_case)] -fn Component(cx: Scope) -> Element { - let theme = use_get_theme(cx); - - let button_theme = &theme.button; - - render!( - rect { - background: "{button_theme.background}", - } - ) -} -``` - -## Change theme globally - -Changing the selected theme at runtime is possible by using the `use_theme` hook. - -```rust, no_run -fn app(cx: Scope) -> Element { - render!( - ThemeProvider { - Component { } - } - ) -} - -#[allow(non_snake_case)] -fn Component(cx: Scope) -> Element { - let theme = use_theme(cx); - - let onclick = |_| { - *theme.write() = LIGHT_THEME; - }; - - render!( - Button { - onclick: onclick, - label { - "Use Light theme" - } - } - ) -} -``` - -## Custom theme - -Themes can be built from scratch or extended from others, like here with `LIGHT_THEME`: - -```rust, no_run -const CUSTOM_THEME: Theme = Theme { - button: ButtonTheme { - background: "rgb(230, 0, 0)", - hover_background: "rgb(150, 0, 0)", - font_theme: FontTheme { color: "white" } - }, - ..LIGHT_THEME -}; - -fn app(cx: Scope) -> Element { - render!( - ThemeProvider { - theme: CUSTOM_THEME, - rect { - width: "100%", - height: "100%", - Button { - label { - "Report" - } - } - } - } - ) -} -``` diff --git a/book/src/guides/virtual_scroll_view.png b/book/src/guides/virtual_scroll_view.png deleted file mode 100644 index 0ce4702de9d6c09f99879d2111a0f114ce5b38e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14708 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 diff --git a/book/src/guides/virtualizing.md b/book/src/guides/virtualizing.md deleted file mode 100644 index 9a22020da..000000000 --- a/book/src/guides/virtualizing.md +++ /dev/null @@ -1,75 +0,0 @@ -# Virtualizing - -Virtualizing helps you render a lot of data efficiently. It will only mount the elements you see in the screen, no matter how big the data is. - -### Target usages -- Text editor -- Tables -- Etc - -### Usage - -Freya comes with a `VirtualScrollView` component which can help you archive the virtualization of some data. - -> The virtualization logic of `VirtualScrollView` is implemented at component-level, so, you could implement your own version if you wanted. - -Here is an example: -```rust, no_run -fn main() { - launch(app); -} - -fn app(cx: Scope) -> Element { - let values = use_state(cx, || vec!["Hello World"].repeat(400)); - - render!( - VirtualScrollView { - width: "100%", - height: "100%", - show_scrollbar: true, - direction: "vertical", - length: values.get().len(), - item_size: 25.0, - builder_values: values.get(), - builder: Box::new(move |(key, index, _cx, values)| { - let values = values.unwrap(); - let value = values[index]; - rsx! { - label { - key: "{key}", - height: "25", - "{index} {value}" - } - } - }) - } - ) -} -``` - - - -
- -![alt text](virtual_scroll_view.png "Virtual ScrollView") - -
- -### Parameters -#### `show_scrollbar` -By default, it does not display a scrollbar. However, you can enable it by setting the `show_scrollbar` parameter to true. - -#### `direction` -It supports both `vertical` and `horizontal` directions. If direction is set to `vertical`, the items will be displayed in a single column, with the scrollbar appearing on the right-hand side. If direction is set to `horizontal`, the items will be displayed in a single row, with the scrollbar appearing at the bottom. - -#### `length` -How many elements can be rendered. Usually the lenth of your data. - -#### `item_size` -Used to calculate how many elements can be fit in the viewport. - -#### `builder_values` -Any data that you might need in the `builder` function - -#### `builder` -This is a function that dinamically creates an element for the given index in the list. It receives 4 arguments, a `key` for the element, the `index` of the element, the Scope (`cx`) and the `builder_values` you previously passed. \ No newline at end of file diff --git a/book/src/index.md b/book/src/index.md index 6eea72d1d..9c5f60216 100644 --- a/book/src/index.md +++ b/book/src/index.md @@ -1,54 +1,77 @@ -> ⚠️ Warning: This Book might contain APIs from the latest [git version](https://github.com/marc2332/freya) that might not be available on the stable versions released on crates.io. -> As a general rule, don't expect everything to be documented here. - -# Welcome +# Overview **Freya** is a **work in progress** cross-platform native GUI library for 🦀 Rust, built on top of 🧬 [Dioxus](https://dioxuslabs.com) and 🎨 [Skia](https://skia.org/) as graphics library. -- [What is Freya?](./what_is_freya.html) -- [Main differences with Dioxus](./differences_with_dioxus.html) -- [Environment Setup](./setup.html) -- [API References](https://docs.rs/freya/latest/freya/) -- [Discord](https://discord.gg/sYejxCdewG) - -
+ ```rust, no_run -fn app(cx: Scope) -> Element { - let mut count = use_state(cx, || 0); +fn app() -> Element { + let mut count = use_signal(|| 0); render!( rect { - height: "20%", + height: "50%", width: "100%", - background: "rgb(233, 196, 106)", - padding: "12", - color: "rgb(20, 33, 61)", - label { - font_size: "20", - "Number is: {count}" + main_align: "center", + cross_align: "center", + background: "rgb(0, 119, 182)", + color: "white", + shadow: "0 4 20 5 rgb(0, 0, 0, 80)", + label { + font_size: "75", + font_weight: "bold", + "{count}" } } rect { - height: "80%", + height: "50%", width: "100%", - background: "rgb(168, 218, 220)", - color: "black", - padding: "12", - onclick: move |_| count += 1, - label { "Click to increase!" } + main_align: "center", + cross_align: "center", + direction: "horizontal", + Button { + onclick: move |_| count += 1, + label { "Increase" } + } + Button { + onclick: move |_| count -= 1, + label { "Decrease" } + } } ) } ``` - -![Freya](./demo.png) - + +
Check out the examples in the Freya [repository](https://github.com/marc2332/freya/tree/main/examples) to learn more. + + +### Features +- ⛏️ Built-in **components** (button, scroll views, switch and more) +- 🚇 Built-in **hooks** library (animations, text editing and more) +- 🔍 Built-in **devtools** panel (experimental ⚠️) +- 🧰 Built-in **headless testing** runner for components +- 🎨 **Theming** support (not extensible yet ⚠️) +- 🛩️ Cross-platform (Windows, Linux, MacOS) +- 🖼️ SKSL **Shaders** support +- 🔄️ Dioxus **Hot-reload** support +- 📒 Multi-line **text editing** (experimental ⚠️) +- 🦾 Basic **Accessibility** Support (experimental ⚠️) +- 🧩Compatible with dioxus-std and other Dioxus renderer-agnostic libraries + +### Learn More + +- [Setup](./setup.html) +- [API References](https://docs.rs/freya/latest/freya/) +- [Main differences with Dioxus](./differences_with_dioxus.html) +- [Discord](https://discord.gg/sYejxCdewG) + diff --git a/book/src/setup.md b/book/src/setup.md index 136373ce6..deee7f0a7 100644 --- a/book/src/setup.md +++ b/book/src/setup.md @@ -1,4 +1,4 @@ -# Environment Setup +# Setup Make sure you have [Rust](https://www.rust-lang.org/) and your OS dependencies installed. diff --git a/book/src/what_is_freya.md b/book/src/what_is_freya.md deleted file mode 100644 index b91d2dc6f..000000000 --- a/book/src/what_is_freya.md +++ /dev/null @@ -1,26 +0,0 @@ -# What is Freya? - -**Freya** is native **GUI** library for Rust🦀, built on top of 🧬 [Dioxus](https://dioxuslabs.com)'s core and powered by 🎨 [Skia](https://skia.org/) as a graphics library. - -### Features -- ⛏️ Built-in **components** (button, scroll views, switch and more) -- 🚇 Built-in **hooks** library (animations, text editing and more) -- 🔍 Built-in **devtools** panel (experimental ⚠️) -- 🧰 Built-in **headless testing** runner for components -- 🎨 **Theming** support (not extensible yet ⚠️) -- 🛩️ Cross-platform (Windows, Linux, MacOS) -- 🖼️ SKSL **Shaders** support -- 🔄️ Dioxus **Hot-reload** support -- 📒 Multi-line **text editing** (experimental ⚠️) -- 🦾 Basic **Accessibility** Support (experimental ⚠️) -- 🧩Compatible with dioxus-std and other Dioxus renderer-agnostic libraries - -### Why 🧬 Dioxus? - -[Dioxus](https://dioxuslabs.com) is a React-like library for Rust. Its component and hooks model make it simple to use and scale to complex apps. -Freya uses some of Dioxus core crates to build it's own renderer, this is because Dioxus is to it's core a renderer-agnostic UI library. -See other [differences](./differences_with_dioxus.html) with Freya. - -### Why 🎨 Skia? - -[Skia](https://skia.org/) is a battle-tested and well-maintained graphics library, and there are even some rusty [bindings](https://github.com/rust-skia/rust-skia).