@@ -160,9 +157,9 @@ You shouldn't use Dioxus if:
## Comparison with other Rust UI frameworks
Dioxus primarily emphasizes **developer experience** and **familiarity with React principles**.
-- [Yew](https://github.com/yewstack/yew): prefers the elm pattern instead of React-hooks, no borrowed props, supports SSR (no hydration).
+- [Yew](https://github.com/yewstack/yew): prefers the elm pattern instead, no borrowed props, supports SSR (no hydration), no direct desktop/mobile support.
- [Percy](https://github.com/chinedufn/percy): Supports SSR but with less emphasis on state management and event handling.
-- [Sycamore](https://github.com/sycamore-rs/sycamore): VDOM-less using fine-grained reactivity, but lacking in ergonomics.
+- [Sycamore](https://github.com/sycamore-rs/sycamore): VDOM-less using fine-grained reactivity, but no direct support for desktop/mobile.
- [Dominator](https://github.com/Pauan/rust-dominator): Signal-based zero-cost alternative, less emphasis on community and docs.
- [Azul](https://azul.rs): Fully native HTML/CSS renderer for desktop applications, no support for web/ssr
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 000000000..325c05ec8
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,2 @@
+comment: false
+fail_ci_if_error: false
diff --git a/docs/fermi/.gitignore b/docs/fermi/.gitignore
new file mode 100644
index 000000000..7585238ef
--- /dev/null
+++ b/docs/fermi/.gitignore
@@ -0,0 +1 @@
+book
diff --git a/docs/fermi/book.toml b/docs/fermi/book.toml
new file mode 100644
index 000000000..dd6d2eacb
--- /dev/null
+++ b/docs/fermi/book.toml
@@ -0,0 +1,6 @@
+[book]
+authors = ["Jonathan Kelley"]
+language = "en"
+multilingual = false
+src = "src"
+title = "Fermi Guide"
diff --git a/docs/fermi/src/SUMMARY.md b/docs/fermi/src/SUMMARY.md
new file mode 100644
index 000000000..7390c8289
--- /dev/null
+++ b/docs/fermi/src/SUMMARY.md
@@ -0,0 +1,3 @@
+# Summary
+
+- [Chapter 1](./chapter_1.md)
diff --git a/docs/fermi/src/chapter_1.md b/docs/fermi/src/chapter_1.md
new file mode 100644
index 000000000..b743fda35
--- /dev/null
+++ b/docs/fermi/src/chapter_1.md
@@ -0,0 +1 @@
+# Chapter 1
diff --git a/docs/guide/src/README.md b/docs/guide/src/README.md
index bbbd9f85f..da6c0156f 100644
--- a/docs/guide/src/README.md
+++ b/docs/guide/src/README.md
@@ -18,7 +18,7 @@ fn app(cx: Scope) -> Element {
In general, Dioxus and React share many functional similarities. If this guide is lacking in any general concept or an error message is confusing, React's documentation might be more helpful. We are dedicated to providing a *familiar* toolkit for UI in Rust, so we've chosen to follow in the footsteps of popular UI frameworks (React, Redux, etc). If you know React, then you already know Dioxus. If you don't know either, this guide will still help you!
-> This is an introduction book! For advanced topics, check out the [Reference](https://dioxuslabs.com/reference) instead.
+> This is an introduction book! For advanced topics, check out the [Reference](/reference) instead.
## Multiplatform
@@ -37,7 +37,7 @@ The Web is the best-supported target platform for Dioxus. To run on the Web, you
Because the web is a fairly mature platform, we expect there to be very little API churn for web-based features.
-[Jump to the getting started guide for the web.]()
+[Jump to the getting started guide for the web.](/reference/platforms/web)
Examples:
- [TodoMVC](https://github.com/DioxusLabs/example-projects/tree/master/todomvc)
@@ -55,7 +55,7 @@ For rendering statically to an `.html` file or from a WebServer, then you'll wan
let contents = dioxus::ssr::render_vdom(&dom);
```
-[Jump to the getting started guide for SSR.]()
+[Jump to the getting started guide for SSR.](/reference/platforms/ssr)
Examples:
- [Example DocSite](https://github.com/dioxusLabs/docsite)
@@ -68,13 +68,13 @@ The desktop is a powerful target for Dioxus, but is currently limited in capabil
Desktop APIs will likely be in flux as we figure out better patterns than our ElectronJS counterpart.
-[Jump to the getting started guide for Desktop.]()
+[Jump to the getting started guide for Desktop.](/reference/platforms/desktop)
Examples:
- [File explorer](https://github.com/dioxusLabs/file-explorer/)
- [WiFi scanner](https://github.com/DioxusLabs/example-projects/blob/master/wifi-scanner)
-[](https://github.com/dioxusLabs/file-explorer/)
+[](https://github.com/DioxusLabs/example-projects/tree/master/file-explorer)
### Mobile Support
---
@@ -82,7 +82,7 @@ Mobile is currently the least-supported renderer target for Dioxus. Mobile apps
Mobile support is currently best suited for CRUD-style apps, ideally for internal teams who need to develop quickly but don't care much about animations or native widgets.
-[Jump to the getting started guide for Mobile.]()
+[Jump to the getting started guide for Mobile.](/reference/platforms/mobile)
Examples:
- [Todo App](https://github.com/DioxusLabs/example-projects/blob/master/ios_demo)
diff --git a/docs/guide/src/components/component_children.md b/docs/guide/src/components/component_children.md
index ea9b1fc45..1259422af 100644
--- a/docs/guide/src/components/component_children.md
+++ b/docs/guide/src/components/component_children.md
@@ -30,7 +30,7 @@ struct ClickableProps<'a> {
title: &'a str
}
-fn Clickable(cx: Scope) -> Element {
+fn Clickable<'a>(cx: Scope<'a, ClickableProps<'a>>) -> Element {
cx.render(rsx!(
a {
href: "{cx.props.href}"
@@ -64,7 +64,7 @@ struct ClickableProps<'a> {
body: Element<'a>
}
-fn Clickable(cx: Scope) -> Element {
+fn Clickable<'a>(cx: Scope<'a, ClickableProps<'a>>) -> Element {
cx.render(rsx!(
a {
href: "{cx.props.href}",
@@ -98,7 +98,7 @@ struct ClickableProps<'a> {
children: Element<'a>
}
-fn Clickable(cx: Scope) -> Element {
+fn Clickable<'a>(cx: Scope<'a, ClickableProps<'a>>) -> Element {
cx.render(rsx!(
a {
href: "{cx.props.href}",
@@ -125,7 +125,7 @@ While technically allowed, it's an antipattern to pass children more than once i
However, because the `Element` is transparently a `VNode`, we can actually match on it to extract the nodes themselves, in case we are expecting a specific format:
```rust
-fn clickable(cx: Scope) -> Element {
+fn clickable<'a>(cx: Scope<'a, ClickableProps<'a>>) -> Element {
match cx.props.children {
Some(VNode::Text(text)) => {
// ...
@@ -160,7 +160,7 @@ struct ClickableProps<'a> {
attributes: Attributes<'a>
}
-fn clickable(cx: Scope) -> Element {
+fn clickable(cx: Scope>) -> Element {
cx.render(rsx!(
a {
..cx.props.attributes,
@@ -184,7 +184,7 @@ struct ClickableProps<'a> {
onclick: EventHandler<'a, MouseEvent>
}
-fn clickable(cx: Scope) -> Element {
+fn clickable<'a>(cx: Scope<'a, ClickableProps<'a>>) -> Element {
cx.render(rsx!(
a {
onclick: move |evt| cx.props.onclick.call(evt)
diff --git a/docs/guide/src/hello_world.md b/docs/guide/src/hello_world.md
index e1d4777d9..6bcc77e30 100644
--- a/docs/guide/src/hello_world.md
+++ b/docs/guide/src/hello_world.md
@@ -63,7 +63,7 @@ $ cat Cargo.toml
[package]
name = "hello-dioxus"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -81,6 +81,13 @@ $ cargo add dioxus --features desktop
It's very important to add `dioxus` with the `desktop` feature for this example. The `dioxus` crate is a batteries-include crate that combines a bunch of utility crates together, ensuring compatibility of the most important parts of the ecosystem. Under the hood, the `dioxus` crate configures various renderers, hooks, debug tooling, and more. The `desktop` feature ensures the we only depend on the smallest set of required crates to compile and render.
+If you system does not provide the `libappindicator3` library, like Debian/bullseye, you can enable the replacement `ayatana` with an additional flag:
+
+```shell
+$ # On Debian/bullseye use:
+$ cargo add dioxus --features desktop --features ayatana
+```
+
If you plan to develop extensions for the `Dioxus` ecosystem, please use the `dioxus` crate with the `core` feature to limit the amount of dependencies your project brings in.
### Our first app
@@ -92,10 +99,10 @@ use dioxus::prelude::*;
fn main() {
- dioxus::desktop::launch(App);
+ dioxus::desktop::launch(app);
}
-fn App(cx: Scope) -> Element {
+fn app(cx: Scope) -> Element {
cx.render(rsx! (
div { "Hello, world!" }
))
@@ -118,14 +125,14 @@ This initialization code launches a Tokio runtime on a helper thread where your
```rust
fn main() {
- dioxus::desktop::launch(App);
+ dioxus::desktop::launch(app);
}
```
Finally, our app. Every component in Dioxus is a function that takes in `Context` and `Props` and returns an `Element`.
```rust
-fn App(cx: Scope) -> Element {
+fn app(cx: Scope) -> Element {
cx.render(rsx! {
div { "Hello, world!" }
})
@@ -143,5 +150,3 @@ For now, just know that `Scope` lets you store state with hooks and render eleme
## Moving on
Congrats! You've built your first desktop application with Dioxus. Next, we're going to learn about the basics of building interactive user interfaces.
-
-
diff --git a/docs/guide/src/interactivity/hooks.md b/docs/guide/src/interactivity/hooks.md
index a90afe2dc..a84a0b129 100644
--- a/docs/guide/src/interactivity/hooks.md
+++ b/docs/guide/src/interactivity/hooks.md
@@ -140,7 +140,7 @@ fn Child(cx: Scope, name: String) -> Element {
// ✅ Or, use a hashmap with use_ref
```rust
-let ages = use_ref(&cx, |_| HashMap::new());
+let ages = use_ref(&cx, || HashMap::new());
names.iter().map(|name| {
let age = ages.get(name).unwrap();
diff --git a/docs/guide/src/setup.md b/docs/guide/src/setup.md
index 1dc9434c5..1bbcec213 100644
--- a/docs/guide/src/setup.md
+++ b/docs/guide/src/setup.md
@@ -8,7 +8,7 @@ We'll learn about:
- Suggested cargo extensions
-For platform-specific guides, check out the [Platform Specific Guides](../platforms/00-index.md).
+For platform-specific guides, check out the [Platform Specific Guides](/reference/platforms/index.md).
# Setting up Dioxus
@@ -52,6 +52,12 @@ Webview Linux apps require WebkitGtk. When distributing, this can be part of you
sudo apt install libwebkit2gtk-4.0-dev libgtk-3-dev libappindicator3-dev
```
+When using Debian/bullseye `libappindicator3-dev` is no longer available but replaced by `libayatana-appindicator3-dev`.
+
+```
+# on Debian/bullseye use:
+sudo apt install libwebkit2gtk-4.0-dev libgtk-3-dev libayatanta-appindicator3-dev
+```
If you run into issues, make sure you have all the basics installed, as outlined in the [Tauri docs](https://tauri.studio/en/docs/get-started/setup-linux).
diff --git a/docs/reference/src/SUMMARY.md b/docs/reference/src/SUMMARY.md
index 3feb9fe36..18f351bfa 100644
--- a/docs/reference/src/SUMMARY.md
+++ b/docs/reference/src/SUMMARY.md
@@ -2,11 +2,12 @@
- [Introduction](README.md)
-- [Web](web/index.md)
-- [Desktop](desktop/index.md)
-- [Mobile](mobile/index.md)
-- [SSR](ssr/index.md)
-- [TUI](tui/index.md)
+- [Platforms](platforms/index.md)
+ - [Web](platforms/web.md)
+ - [Server Side Rendering](platforms/ssr.md)
+ - [Desktop](platforms/desktop.md)
+ - [Mobile](platforms/mobile.md)
+ - [TUI](platforms/tui.md)
- [Advanced Guides](guide/index.md)
- [RSX in Depth](guide/rsx_in_depth.md)
diff --git a/docs/reference/src/desktop/index.md b/docs/reference/src/platforms/desktop.md
similarity index 98%
rename from docs/reference/src/desktop/index.md
rename to docs/reference/src/platforms/desktop.md
index 8011f1eed..18393f132 100644
--- a/docs/reference/src/desktop/index.md
+++ b/docs/reference/src/platforms/desktop.md
@@ -1,4 +1,4 @@
-# Desktop
+# Getting Started: Desktop
One of Dioxus' killer features is the ability to quickly build a native desktop app that looks and feels the same across platforms. Apps built with Dioxus are typically <5mb in size and use existing system resources, so they won't hog extreme amounts of RAM or memory.
diff --git a/docs/reference/src/platforms/index.md b/docs/reference/src/platforms/index.md
new file mode 100644
index 000000000..fbbabd35d
--- /dev/null
+++ b/docs/reference/src/platforms/index.md
@@ -0,0 +1,10 @@
+# Platforms
+
+Dioxus supports many different platforms. Below are a list of guides that walk you through setting up Dioxus for a specific platform.
+
+### Setup Guides
+- [Web](web.md)
+- [Server Side Rendering](ssr.md)
+- [Desktop](desktop.md)
+- [Mobile](mobile.md)
+- [TUI](tui.md)
\ No newline at end of file
diff --git a/docs/reference/src/mobile/index.md b/docs/reference/src/platforms/mobile.md
similarity index 99%
rename from docs/reference/src/mobile/index.md
rename to docs/reference/src/platforms/mobile.md
index 2e8344ed1..5a41ffe60 100644
--- a/docs/reference/src/mobile/index.md
+++ b/docs/reference/src/platforms/mobile.md
@@ -21,7 +21,7 @@ $ cargo install --git https://github.com/BrainiumLLC/cargo-mobile
And then initialize your app for the right platform. Use the `winit` template for now. Right now, there's no "Dioxus" template in cargo-mobile.
```shell
-$ cargo moble init
+$ cargo mobile init
```
We're going to completely clear out the `dependencies` it generates for us, swapping out `winit` with `dioxus-mobile`.
diff --git a/docs/reference/src/ssr/index.md b/docs/reference/src/platforms/ssr.md
similarity index 88%
rename from docs/reference/src/ssr/index.md
rename to docs/reference/src/platforms/ssr.md
index aef223dfd..09e32ba43 100644
--- a/docs/reference/src/ssr/index.md
+++ b/docs/reference/src/platforms/ssr.md
@@ -2,11 +2,8 @@
The Dioxus VirtualDom can be rendered to a string by traversing the Element Tree. This is implemented in the `ssr` crate where your Dioxus app can be directly rendered to HTML to be served by a web server.
-
-
## Setup
-
If you just want to render `rsx!` or a VirtualDom to HTML, check out the API docs. It's pretty simple:
```rust
@@ -19,8 +16,7 @@ println!("{}", dioxus::ssr::render_vdom(&vdom));
println!( "{}", dioxus::ssr::render_lazy(rsx! { h1 { "Hello, world!" } } );
```
-
-However, for this guide, we're going to show how to use Dioxus SSR with `Axum`.
+However, for this guide, we're going to show how to use Dioxus SSR with `Axum`.
Make sure you have Rust and Cargo installed, and then create a new project:
@@ -29,15 +25,16 @@ $ cargo new --bin demo
$ cd app
```
-Add Dioxus with the `desktop` feature:
+Add Dioxus with the `ssr` feature:
```shell
$ cargo add dioxus --features ssr
```
Next, add all the Axum dependencies. This will be different if you're using a different Web Framework
+
```
-$ cargo add dioxus tokio --features full
+$ cargo add tokio --features full
$ cargo add axum
```
@@ -45,12 +42,11 @@ Your dependencies should look roughly like this:
```toml
[dependencies]
-axum = "0.4.3"
+axum = "0.4.5"
dioxus = { version = "*", features = ["ssr"] }
tokio = { version = "1.15.0", features = ["full"] }
```
-
Now, setup your Axum app to respond on an endpoint.
```rust
@@ -63,7 +59,11 @@ async fn main() {
println!("listening on http://{}", addr);
axum::Server::bind(&addr)
- .serve(Router::new().route("/", get(app_endpoint)))
+ .serve(
+ Router::new()
+ .route("/", get(app_endpoint))
+ .into_make_service(),
+ )
.await
.unwrap();
}
@@ -88,14 +88,14 @@ async fn app_endpoint() -> Html {
}
let mut app = VirtualDom::new(app);
let _ = app.rebuild();
-
+
Html(dioxus::ssr::render_vdom(&app))
}
```
And that's it!
-> You might notice that you cannot hold the VirtualDom across an await point. Dioxus is currently not ThreadSafe, so it *must* remain on the thread it started. We are working on loosening this requirement.
+> You might notice that you cannot hold the VirtualDom across an await point. Dioxus is currently not ThreadSafe, so it _must_ remain on the thread it started. We are working on loosening this requirement.
## Future Steps
diff --git a/docs/reference/src/tui/index.md b/docs/reference/src/platforms/tui.md
similarity index 98%
rename from docs/reference/src/tui/index.md
rename to docs/reference/src/platforms/tui.md
index 3947883d4..e646bd4ba 100644
--- a/docs/reference/src/tui/index.md
+++ b/docs/reference/src/platforms/tui.md
@@ -1,4 +1,4 @@
-# TUI
+# Getting Started: TUI
TUI support is currently quite experimental. Even the project name will change. But, if you're willing to venture into the realm of the unknown, this guide will get you started.
diff --git a/docs/reference/src/web/index.md b/docs/reference/src/platforms/web.md
similarity index 98%
rename from docs/reference/src/web/index.md
rename to docs/reference/src/platforms/web.md
index 062cba177..2ff5f621e 100644
--- a/docs/reference/src/web/index.md
+++ b/docs/reference/src/platforms/web.md
@@ -1,4 +1,4 @@
-# Getting Started: Dioxus for Web
+# Getting Started: Web
[*"Pack your things, we're going on an adventure!"*](https://trunkrs.dev)
diff --git a/examples/borderless.rs b/examples/borderless.rs
deleted file mode 100644
index d52e9fb5a..000000000
--- a/examples/borderless.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
- dioxus::desktop::launch_cfg(app, |cfg| {
- cfg.with_window(|w| w.with_title("BorderLess Demo").with_decorations(false))
- });
-}
-
-fn app(cx: Scope) -> Element {
- let window = dioxus::desktop::use_window(&cx);
-
- cx.render(rsx!(
- link { href:"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css", rel:"stylesheet" }
- header {
- class: "text-gray-400 bg-gray-900 body-font",
- onmousedown: move |_| window.drag(),
- div {
- class: "container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center",
- a { class: "flex title-font font-medium items-center text-white mb-4 md:mb-0",
- span { class: "ml-3 text-xl", "Dioxus"}
- }
- nav { class: "md:ml-auto flex flex-wrap items-center text-base justify-center" }
- button {
- class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
- onmousedown: |evt| evt.cancel_bubble(),
- onclick: move |_| window.minimize(true),
- "Minimize"
- }
- button {
- class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
- onmousedown: |evt| evt.cancel_bubble(),
- onclick: move |_| window.close(),
- "Close"
- }
- }
- }
- ))
-}
diff --git a/examples/dog_app.rs b/examples/dog_app.rs
index a30f3e5e8..ad983035e 100644
--- a/examples/dog_app.rs
+++ b/examples/dog_app.rs
@@ -16,7 +16,9 @@ struct ListBreeds {
}
fn app(cx: Scope) -> Element {
- let breeds = use_future(&cx, || async move {
+ let (breed, set_breed) = use_state(&cx, || None);
+
+ let breeds = use_future(&cx, (), |_| async move {
reqwest::get("https://dog.ceo/api/breeds/list/all")
.await
.unwrap()
@@ -24,13 +26,10 @@ fn app(cx: Scope) -> Element {
.await
});
- let (breed, set_breed) = use_state(&cx, || None);
-
match breeds.value() {
Some(Ok(breeds)) => cx.render(rsx! {
div {
- h1 {"Select a dog breed!"}
-
+ h1 { "Select a dog breed!" }
div { display: "flex",
ul { flex: "50%",
breeds.message.keys().map(|breed| rsx!(
@@ -51,34 +50,23 @@ fn app(cx: Scope) -> Element {
}
}
}),
- Some(Err(_e)) => cx.render(rsx! {
- div { "Error fetching breeds" }
- }),
- None => cx.render(rsx! {
- div { "Loading dogs..." }
- }),
+ Some(Err(_e)) => cx.render(rsx! { div { "Error fetching breeds" } }),
+ None => cx.render(rsx! { div { "Loading dogs..." } }),
}
}
+#[derive(serde::Deserialize, Debug)]
+struct DogApi {
+ message: String,
+}
+
#[inline_props]
fn Breed(cx: Scope, breed: String) -> Element {
- #[derive(serde::Deserialize, Debug)]
- struct DogApi {
- message: String,
- }
-
- let endpoint = format!("https://dog.ceo/api/breed/{}/images/random", breed);
-
- let fut = use_future(&cx, || async move {
+ let fut = use_future(&cx, (breed,), |(breed,)| async move {
+ let endpoint = format!("https://dog.ceo/api/breed/{}/images/random", breed);
reqwest::get(endpoint).await.unwrap().json::().await
});
- let (name, set_name) = use_state(&cx, || breed.clone());
- if name != breed {
- set_name(breed.clone());
- fut.restart();
- }
-
cx.render(match fut.value() {
Some(Ok(resp)) => rsx! {
button {
diff --git a/examples/fermi.rs b/examples/fermi.rs
new file mode 100644
index 000000000..2be01d019
--- /dev/null
+++ b/examples/fermi.rs
@@ -0,0 +1,30 @@
+#![allow(non_snake_case)]
+
+use dioxus::prelude::*;
+use fermi::prelude::*;
+
+fn main() {
+ dioxus::desktop::launch(app)
+}
+
+static NAME: Atom = |_| "world".to_string();
+
+fn app(cx: Scope) -> Element {
+ let name = use_read(&cx, NAME);
+
+ cx.render(rsx! {
+ div { "hello {name}!" }
+ Child {}
+ })
+}
+
+fn Child(cx: Scope) -> Element {
+ let set_name = use_set(&cx, NAME);
+
+ cx.render(rsx! {
+ button {
+ onclick: move |_| set_name("dioxus".to_string()),
+ "reset name"
+ }
+ })
+}
diff --git a/examples/heavy_compute.rs b/examples/heavy_compute.rs
new file mode 100644
index 000000000..6e10a2f1f
--- /dev/null
+++ b/examples/heavy_compute.rs
@@ -0,0 +1,28 @@
+//! This example shows that you can place heavy work on the main thread, and then
+//!
+//! You *should* be using `tokio::spawn_blocking` instead.
+//!
+//! Your app runs in an async runtime (Tokio), so you should avoid blocking
+//! the rendering of the VirtualDom.
+//!
+//!
+
+use dioxus::prelude::*;
+
+fn main() {
+ dioxus::desktop::launch(app);
+}
+
+fn app(cx: Scope) -> Element {
+ // This is discouraged
+ std::thread::sleep(std::time::Duration::from_millis(2_000));
+
+ // This is suggested
+ tokio::task::spawn_blocking(move || {
+ std::thread::sleep(std::time::Duration::from_millis(2_000));
+ });
+
+ cx.render(rsx! {
+ div { "Hello, world!" }
+ })
+}
diff --git a/examples/login_form.rs b/examples/login_form.rs
new file mode 100644
index 000000000..0a0c77e87
--- /dev/null
+++ b/examples/login_form.rs
@@ -0,0 +1,50 @@
+//! This example demonstrates the following:
+//! Futures in a callback, Router, and Forms
+
+use dioxus::events::*;
+use dioxus::prelude::*;
+
+fn main() {
+ dioxus::desktop::launch(app);
+}
+
+fn app(cx: Scope) -> Element {
+ let onsubmit = move |evt: FormEvent| {
+ cx.spawn(async move {
+ let resp = reqwest::Client::new()
+ .post("http://localhost:8080/login")
+ .form(&[
+ ("username", &evt.values["username"]),
+ ("password", &evt.values["password"]),
+ ])
+ .send()
+ .await;
+
+ match resp {
+ // Parse data from here, such as storing a response token
+ Ok(_data) => println!("Login successful!"),
+
+ //Handle any errors from the fetch here
+ Err(_err) => {
+ println!("Login failed - you need a login server running on localhost:8080.")
+ }
+ }
+ });
+ };
+
+ cx.render(rsx! {
+ h1 { "Login" }
+ form {
+ onsubmit: onsubmit,
+ prevent_default: "onsubmit", // Prevent the default behavior of