Merge branch 'master' into add-file-data-drag-event

This commit is contained in:
Evan Almloff committed 2023-09-17 18:56:59 -05:00
commit 847801908f
575 files changed
+12880 -17751

No files matched your search

+3 -2
View File
@@ -3,12 +3,13 @@ name = "dioxus-pwa-example"
version = "0.1.0"
authors = ["Antonio Curavalea <one.kyonblack@gmail.com>"]
edition = "2021"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus = { path = "../../packages/dioxus", version = "^0.3.0"}
dioxus-web = { path = "../../packages/web", version = "^0.3.0"}
dioxus = { path = "../../packages/dioxus", version = "*" }
dioxus-web = { path = "../../packages/web", version = "*" }
log = "0.4.6"
+6 -5
View File
@@ -7,12 +7,13 @@ It is also very much usable as a template for your projects, if you're aiming to
## Try the example
Make sure you have Dioxus CLI installed (if you're unsure, run `cargo install dioxus-cli`).
Make sure you have Dioxus CLI installed (if you're unsure, run `cargo install dioxus-cli --locked`).
You can run `dx serve` in this directory to start the web server locally, or run
`dx build --release` to build the project so you can deploy it on a separate web-server.
## Project Structure
```
├── Cargo.toml
├── Dioxus.toml
@@ -33,12 +34,12 @@ You can run `dx serve` in this directory to start the web server locally, or run
If you're just getting started with PWAs, here are some useful resources:
* [PWABuilder docs](https://docs.pwabuilder.com/#/)
* [MDN article on PWAs](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps)
- [PWABuilder docs](https://docs.pwabuilder.com/#/)
- [MDN article on PWAs](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps)
For service worker scripting (in JavaScript):
* [Service worker guide from PWABuilder](https://docs.pwabuilder.com/#/home/sw-intro)
* [Service worker examples, also from PWABuilder](https://github.com/pwa-builder/pwabuilder-serviceworkers)
- [Service worker guide from PWABuilder](https://docs.pwabuilder.com/#/home/sw-intro)
- [Service worker examples, also from PWABuilder](https://github.com/pwa-builder/pwabuilder-serviceworkers)
If you want to stay as close to 100% Rust as possible, you can try using [wasi-worker](https://github.com/dunnock/wasi-worker) to replace the JS service worker file. The JSON manifest will still be required though.
+1 -7
View File
@@ -1,17 +1,11 @@
//! Example: README.md showcase
//!
//! The example from the README.md.
use dioxus::prelude::*;
use dioxus_signals::{use_init_signal_rt, use_signal};
use dioxus_signals::use_signal;
fn main() {
dioxus_desktop::launch(app);
}
fn app(cx: Scope) -> Element {
use_init_signal_rt(cx);
let mut count = use_signal(cx, || 0);
use_future!(cx, || async move {
+9 -9
View File
@@ -1,5 +1,4 @@
//! Tiny CRM: A port of the Yew CRM example to Dioxus.
#![allow(non_snake_case)]
use dioxus::prelude::*;
use dioxus_router::prelude::*;
@@ -27,6 +26,7 @@ pub struct Client {
type ClientContext = Vec<Client>;
#[component]
fn App(cx: Scope) -> Element {
use_shared_state_provider::<ClientContext>(cx, Default::default);
@@ -46,11 +46,11 @@ fn App(cx: Scope) -> Element {
h1 { "Dioxus CRM Example" }
Router {}
Router::<Route> {}
}
}
#[inline_props]
#[component]
fn ClientList(cx: Scope) -> Element {
let clients = use_shared_state::<ClientContext>(cx).unwrap();
@@ -58,12 +58,12 @@ fn ClientList(cx: Scope) -> Element {
h2 { "List of Clients" }
Link {
target: Route::ClientAdd {},
to: Route::ClientAdd {},
class: "pure-button pure-button-primary",
"Add Client"
}
Link {
target: Route::Settings {},
to: Route::Settings {},
class: "pure-button",
"Settings"
}
@@ -80,7 +80,7 @@ fn ClientList(cx: Scope) -> Element {
})
}
#[inline_props]
#[component]
fn ClientAdd(cx: Scope) -> Element {
let clients = use_shared_state::<ClientContext>(cx).unwrap();
let first_name = use_state(cx, String::new);
@@ -161,7 +161,7 @@ fn ClientAdd(cx: Scope) -> Element {
"Save"
}
Link {
target: Route::ClientList {},
to: Route::ClientList {},
class: "pure-button pure-button-primary red",
"Cancel"
}
@@ -173,7 +173,7 @@ fn ClientAdd(cx: Scope) -> Element {
})
}
#[inline_props]
#[component]
fn Settings(cx: Scope) -> Element {
let clients = use_shared_state::<ClientContext>(cx).unwrap();
@@ -190,7 +190,7 @@ fn Settings(cx: Scope) -> Element {
}
Link {
target: Route::ClientList {},
to: Route::ClientList {},
class: "pure-button",
"Go back"
}
+6 -5
View File
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
use std::collections::HashMap;
fn main() {
dioxus_desktop::launch(|cx| render!(app_root {}));
dioxus_desktop::launch(|cx| render!(AppRoot {}));
}
#[derive(Debug, Clone, PartialEq, serde::Deserialize)]
@@ -10,7 +10,8 @@ struct ListBreeds {
message: HashMap<String, Vec<String>>,
}
fn app_root(cx: Scope<'_>) -> Element {
#[component]
fn AppRoot(cx: Scope<'_>) -> Element {
let breed = use_state(cx, || "deerhound".to_string());
let breeds = use_future!(cx, || async move {
@@ -36,7 +37,7 @@ fn app_root(cx: Scope<'_>) -> Element {
}
}
}
div { flex: "50%", breed_pic { breed: breed.to_string() } }
div { flex: "50%", BreedPic { breed: breed.to_string() } }
}
}
}),
@@ -49,8 +50,8 @@ struct DogApi {
message: String,
}
#[inline_props]
fn breed_pic(cx: Scope, breed: String) -> Element {
#[component]
fn BreedPic(cx: Scope, breed: String) -> Element {
let fut = use_future!(cx, |breed| async move {
reqwest::get(format!("https://dog.ceo/api/breed/{breed}/images/random"))
.await
+6 -5
View File
@@ -1,10 +1,11 @@
use dioxus::prelude::*;
fn main() {
dioxus_desktop::launch(app);
dioxus_desktop::launch(App);
}
fn app(cx: Scope) -> Element {
#[component]
fn App(cx: Scope) -> Element {
let val = use_state(cx, || "0.0001");
let num = match val.parse::<f32>() {
@@ -19,13 +20,13 @@ fn app(cx: Scope) -> Element {
"Set an invalid number"
}
(0..5).map(|i| rsx! {
demo_c { x: i }
DemoC { x: i }
})
})
}
#[inline_props]
fn demo_c(cx: Scope, x: i32) -> Element {
#[component]
fn DemoC(cx: Scope, x: i32) -> Element {
cx.render(rsx! {
h1 {
"asdasdasdasd {x}"
+28 -23
View File
@@ -5,29 +5,34 @@ fn main() {
}
fn app(cx: Scope) -> Element {
let eval = dioxus_desktop::use_eval(cx);
let script = use_state(cx, String::new);
let output = use_state(cx, String::new);
let eval_provider = use_eval(cx);
cx.render(rsx! {
div {
p { "Output: {output}" }
input {
placeholder: "Enter an expression",
value: "{script}",
oninput: move |e| script.set(e.value.clone()),
}
button {
onclick: move |_| {
to_owned![script, eval, output];
cx.spawn(async move {
if let Ok(res) = eval(script.to_string()).await {
output.set(res.to_string());
}
});
},
"Execute"
}
let future = use_future(cx, (), |_| {
to_owned![eval_provider];
async move {
let eval = eval_provider(
r#"
dioxus.send("Hi from JS!");
let msg = await dioxus.recv();
console.log(msg);
return "hello world";
"#,
)
.unwrap();
eval.send("Hi from Rust!".into()).unwrap();
let res = eval.recv().await.unwrap();
println!("{:?}", eval.await);
res
}
})
});
match future.value() {
Some(v) => cx.render(rsx!(
p { "{v}" }
)),
_ => cx.render(rsx!(
p { "hello" }
)),
}
}
+14 -15
View File
@@ -1,5 +1,3 @@
#![allow(non_snake_case)]
use dioxus::prelude::*;
use dioxus_desktop::{tao::dpi::LogicalSize, Config, WindowBuilder};
use dioxus_router::prelude::*;
@@ -13,12 +11,13 @@ fn main() {
.with_resizable(false),
);
dioxus_desktop::launch_cfg(app, cfg)
dioxus_desktop::launch_cfg(App, cfg)
}
fn app(cx: Scope) -> Element {
#[component]
fn App(cx: Scope) -> Element {
render! {
Router {}
Router::<Route> {}
}
}
@@ -36,11 +35,11 @@ enum Route {
Settings {},
}
#[inline_props]
#[component]
fn Footer(cx: Scope) -> Element {
render! {
div {
Outlet { }
Outlet::<Route> { }
p {
"----"
@@ -48,32 +47,32 @@ fn Footer(cx: Scope) -> Element {
nav {
ul {
li { Link { target: Route::Home {}, "Home" } }
li { Link { target: Route::Games {}, "Games" } }
li { Link { target: Route::Play {}, "Play" } }
li { Link { target: Route::Settings {}, "Settings" } }
li { Link { to: Route::Home {}, "Home" } }
li { Link { to: Route::Games {}, "Games" } }
li { Link { to: Route::Play {}, "Play" } }
li { Link { to: Route::Settings {}, "Settings" } }
}
}
}
}
}
#[inline_props]
#[component]
fn Home(cx: Scope) -> Element {
render!("Home")
}
#[inline_props]
#[component]
fn Games(cx: Scope) -> Element {
render!("Games")
}
#[inline_props]
#[component]
fn Play(cx: Scope) -> Element {
render!("Play")
}
#[inline_props]
#[component]
fn Settings(cx: Scope) -> Element {
render!("Settings")
}
+2 -1
View File
@@ -13,7 +13,8 @@ use dioxus::prelude::*;
use dioxus_desktop::Config;
fn main() {
let vdom = VirtualDom::new(app);
let mut vdom = VirtualDom::new(app);
let _ = vdom.rebuild();
let content = dioxus_ssr::pre_render(&vdom);
dioxus_desktop::launch_cfg(app, Config::new().with_prerendered(content));
+11 -9
View File
@@ -1,33 +1,35 @@
//! Run with `cargo-expand` to see what each one expands to
#![allow(non_snake_case)]
//! Run with `cargo-expand` to see what each one expands to.
//! This file is named `inlineprops.rs`, because there used to be a `#[inline_props]` macro to
//! do this. However, it's now deprecated (and will likely be removed in a future major version),
//! so please use `#[component]` instead!
use dioxus::prelude::*;
#[inline_props]
#[component]
fn Thing1<T>(cx: Scope, _a: T) -> Element {
cx.render(rsx! { "" })
}
#[inline_props]
#[component]
fn Thing2(cx: Scope, _a: u32) -> Element<'a> {
cx.render(rsx! { "" })
}
#[inline_props]
#[component]
fn Thing3<'a, T>(cx: Scope<'a>, _a: &'a T) -> Element<'a> {
cx.render(rsx! { "" })
}
#[inline_props]
#[component]
fn Thing4<'a>(cx: Scope<'a>, _a: &'a u32) -> Element<'a> {
cx.render(rsx! { "" })
}
fn main() {
dioxus_desktop::launch(app);
dioxus_desktop::launch(App);
}
fn app(cx: Scope) -> Element {
#[component]
fn App(cx: Scope) -> Element {
let state = use_state(cx, || 1);
cx.render(rsx! {
+10 -11
View File
@@ -1,13 +1,12 @@
#![allow(non_snake_case)]
use dioxus::prelude::*;
use dioxus_router::prelude::*;
fn main() {
dioxus_desktop::launch(app);
dioxus_desktop::launch(App);
}
fn app(cx: Scope) -> Element {
#[component]
fn App(cx: Scope) -> Element {
cx.render(rsx! (
div {
p {
@@ -23,7 +22,7 @@ fn app(cx: Scope) -> Element {
}
}
div {
Router {}
Router::<Route> {}
}
))
}
@@ -38,24 +37,24 @@ enum Route {
Settings {},
}
#[inline_props]
#[component]
fn Header(cx: Scope) -> Element {
render! {
h1 { "Your app here" }
ul {
li { Link { target: Route::Home {}, "home" } }
li { Link { target: Route::Settings {}, "settings" } }
li { Link { to: Route::Home {}, "home" } }
li { Link { to: Route::Settings {}, "settings" } }
}
Outlet {}
Outlet::<Route> {}
}
}
#[inline_props]
#[component]
fn Home(cx: Scope) -> Element {
render!(h1 { "Home" })
}
#[inline_props]
#[component]
fn Settings(cx: Scope) -> Element {
render!(h1 { "Settings" })
}
-1
View File
@@ -35,7 +35,6 @@ fn app(cx: Scope) -> Element {
h1 { "Login" }
form {
onsubmit: onsubmit,
prevent_default: "onsubmit", // Prevent the default behavior of <form> to post
input { r#type: "text", id: "username", name: "username" }
label { "Username" }
br {}
+1 -1
View File
@@ -72,7 +72,7 @@ fn app(cx: Scope) -> Element {
onclick: move|_| {
println!("Clicked!");
items.push(items.len());
cx.needs_update_any(ScopeId(0));
cx.needs_update_any(ScopeId::ROOT);
println!("Requested update");
},
"Add item"
+12
View File
@@ -0,0 +1,12 @@
[package]
name = "query_segments_demo"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus = { path = "../../packages/dioxus", version = "*" }
dioxus-router = { path = "../../packages/router", version = "*" }
dioxus-web = { path = "../../packages/web", version = "*" }
form_urlencoded = "1.2.0"
+74
View File
@@ -0,0 +1,74 @@
#![allow(unused)]
//! Example: Url query segments usage
//! ------------------------------------
//!
//! This example shows how to access and use multiple query segments present in an url on the web.
//!
//! Run `dx serve` and navigate to `http://localhost:8080/blog?name=John&surname=Doe`
use std::fmt::Display;
use dioxus::prelude::*;
use dioxus_router::prelude::*;
// ANCHOR: route
#[derive(Routable, Clone)]
#[rustfmt::skip]
enum Route {
// segments that start with ?: are query segments
#[route("/blog?:query_params")]
BlogPost {
// You must include query segments in child variants
query_params: BlogQuerySegments,
},
}
#[derive(Debug, Clone, PartialEq)]
struct BlogQuerySegments {
name: String,
surname: String,
}
/// The display impl needs to display the query in a way that can be parsed:
impl Display for BlogQuerySegments {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "name={}&surname={}", self.name, self.surname)
}
}
/// The query segment is anything that implements https://docs.rs/dioxus-router/latest/dioxus_router/routable/trait.FromQuery.html. You can implement that trait for a struct if you want to parse multiple query parameters.
impl FromQuery for BlogQuerySegments {
fn from_query(query: &str) -> Self {
let mut name = None;
let mut surname = None;
let pairs = form_urlencoded::parse(query.as_bytes());
pairs.for_each(|(key, value)| {
if key == "name" {
name = Some(value.clone().into());
}
if key == "surname" {
surname = Some(value.clone().into());
}
});
Self {
name: name.unwrap(),
surname: surname.unwrap(),
}
}
}
#[component]
fn BlogPost(cx: Scope, query_params: BlogQuerySegments) -> Element {
render! {
div{"This is your blogpost with a query segment:"}
div{format!("{:?}", query_params)}
}
}
#[component]
fn App(cx: Scope) -> Element {
render! { Router::<Route>{} }
}
fn main() {
dioxus_web::launch(App);
}
+14 -15
View File
@@ -1,5 +1,3 @@
#![allow(non_snake_case)]
use dioxus::prelude::*;
use dioxus_router::prelude::*;
@@ -37,54 +35,55 @@ enum Route {
}
// ANCHOR_END: router
#[component]
fn App(cx: Scope) -> Element {
render! {
Router {}
Router::<Route> {}
}
}
#[inline_props]
#[component]
fn NavBar(cx: Scope) -> Element {
render! {
nav {
ul {
li { Link { target: Route::Home {}, "Home" } }
li { Link { target: Route::BlogList {}, "Blog" } }
li { Link { to: Route::Home {}, "Home" } }
li { Link { to: Route::BlogList {}, "Blog" } }
}
}
Outlet {}
Outlet::<Route> {}
}
}
#[inline_props]
#[component]
fn Home(cx: Scope) -> Element {
render! {
h1 { "Welcome to the Dioxus Blog!" }
}
}
#[inline_props]
#[component]
fn Blog(cx: Scope) -> Element {
render! {
h1 { "Blog" }
Outlet {}
Outlet::<Route> {}
}
}
#[inline_props]
#[component]
fn BlogList(cx: Scope) -> Element {
render! {
h2 { "Choose a post" }
ul {
li {
Link {
target: Route::BlogPost { name: "Blog post 1".into() },
to: Route::BlogPost { name: "Blog post 1".into() },
"Read the first blog post"
}
}
li {
Link {
target: Route::BlogPost { name: "Blog post 2".into() },
to: Route::BlogPost { name: "Blog post 2".into() },
"Read the second blog post"
}
}
@@ -92,14 +91,14 @@ fn BlogList(cx: Scope) -> Element {
}
}
#[inline_props]
#[component]
fn BlogPost(cx: Scope, name: String) -> Element {
render! {
h2 { "Blog Post: {name}"}
}
}
#[inline_props]
#[component]
fn PageNotFound(cx: Scope, route: Vec<String>) -> Element {
render! {
h1 { "Page not found" }
+17 -10
View File
@@ -1,4 +1,3 @@
#![allow(non_snake_case)]
//! A tour of the rsx! macro
//! ------------------------
//!
@@ -40,7 +39,7 @@
//! - Allow top-level fragments
fn main() {
dioxus_desktop::launch(app);
dioxus_desktop::launch(App);
}
use core::{fmt, str::FromStr};
@@ -49,7 +48,8 @@ use std::fmt::Display;
use baller::Baller;
use dioxus::prelude::*;
fn app(cx: Scope) -> Element {
#[component]
fn App(cx: Scope) -> Element {
let formatting = "formatting!";
let formatting_tuple = ("a", "b");
let lazy_fmt = format_args!("lazily formatted text");
@@ -217,12 +217,16 @@ fn format_dollars(dollars: u32, cents: u32) -> String {
format!("${dollars}.{cents:02}")
}
fn helper<'a>(cx: &'a ScopeState, text: &str) -> Element<'a> {
fn helper<'a>(cx: &'a ScopeState, text: &'a str) -> Element<'a> {
cx.render(rsx! {
p { "{text}" }
})
}
// no_case_check disables PascalCase checking if you *really* want a snake_case component.
// This will likely be deprecated/removed in a future update that will introduce a more polished linting system,
// something like Clippy.
#[component(no_case_check)]
fn lowercase_helper(cx: Scope) -> Element {
cx.render(rsx! {
"asd"
@@ -234,12 +238,16 @@ mod baller {
#[derive(Props, PartialEq, Eq)]
pub struct BallerProps {}
#[allow(non_snake_case)]
#[component]
/// This component totally balls
pub fn Baller(_: Scope<BallerProps>) -> Element {
pub fn Baller(_cx: Scope<BallerProps>) -> Element {
todo!()
}
// no_case_check disables PascalCase checking if you *really* want a snake_case component.
// This will likely be deprecated/removed in a future update that will introduce a more polished linting system,
// something like Clippy.
#[component(no_case_check)]
pub fn lowercase_component(cx: Scope) -> Element {
cx.render(rsx! { "look ma, no uppercase" })
}
@@ -253,7 +261,7 @@ pub struct TallerProps<'a> {
}
/// Documention for this component is visible within the rsx macro
#[allow(non_snake_case)]
#[component]
pub fn Taller<'a>(cx: Scope<'a, TallerProps<'a>>) -> Element {
cx.render(rsx! {
&cx.props.children
@@ -275,15 +283,14 @@ where
todo!()
}
#[inline_props]
#[component]
fn WithInline<'a>(cx: Scope<'a>, text: &'a str) -> Element {
cx.render(rsx! {
p { "{text}" }
})
}
// generic component with inline_props too
#[inline_props]
#[component]
fn Label<T>(cx: Scope, text: T) -> Element
where
T: Display,
+3 -4
View File
@@ -1,5 +1,3 @@
#![allow(non_snake_case)]
use std::collections::HashMap;
use dioxus::prelude::*;
@@ -27,6 +25,7 @@ impl CoolData {
}
}
#[component]
#[rustfmt::skip]
pub fn App(cx: Scope) -> Element {
use_shared_state_provider(cx, || CoolData::new(HashMap::from([
@@ -50,7 +49,7 @@ pub fn App(cx: Scope) -> Element {
)
}
#[inline_props]
#[component]
fn DataEditor(cx: Scope, id: usize) -> Element {
let cool_data = use_shared_state::<CoolData>(cx).unwrap().read();
@@ -61,7 +60,7 @@ fn DataEditor(cx: Scope, id: usize) -> Element {
})
}
#[inline_props]
#[component]
fn DataView(cx: Scope, id: usize) -> Element {
let cool_data = use_shared_state::<CoolData>(cx).unwrap();
+1 -1
View File
@@ -20,7 +20,7 @@ fn app(cx: Scope) -> Element {
button { onclick: move |_| count += 1, "Up high!" }
button { onclick: move |_| count -= 1, "Down low!" }
if count() > 5 {
if count.value() > 5 {
rsx!{ h2 { "High five!" } }
}
})
+16 -15
View File
@@ -9,12 +9,13 @@ fn main() {
.with_module_level("dioxus", log::LevelFilter::Trace)
.init()
.unwrap();
dioxus_desktop::launch(app);
dioxus_desktop::launch(App);
}
fn app(cx: Scope) -> Element {
#[component]
fn App(cx: Scope) -> Element {
render! {
Router {}
Router::<Route> {}
}
}
@@ -36,46 +37,46 @@ enum Route {
Oranges {},
}
#[inline_props]
#[component]
fn NavBar(cx: Scope) -> Element {
render! {
h1 { "Your app here" }
ul {
li { Link { target: Route::Home {}, "home" } }
li { Link { target: Route::BlogList {}, "blog" } }
li { Link { target: Route::BlogPost { post: "tim".into() }, "tims' blog" } }
li { Link { target: Route::BlogPost { post: "bill".into() }, "bills' blog" } }
li { Link { target: Route::BlogPost { post: "james".into() }, "james amazing' blog" } }
li { Link { to: Route::Home {}, "home" } }
li { Link { to: Route::BlogList {}, "blog" } }
li { Link { to: Route::BlogPost { post: "tim".into() }, "tims' blog" } }
li { Link { to: Route::BlogPost { post: "bill".into() }, "bills' blog" } }
li { Link { to: Route::BlogPost { post: "james".into() }, "james amazing' blog" } }
}
Outlet {}
Outlet::<Route> {}
}
}
#[inline_props]
#[component]
fn Home(cx: Scope) -> Element {
log::debug!("rendering home {:?}", cx.scope_id());
render! { h1 { "Home" } }
}
#[inline_props]
#[component]
fn BlogList(cx: Scope) -> Element {
log::debug!("rendering blog list {:?}", cx.scope_id());
render! { div { "Blog List" } }
}
#[inline_props]
#[component]
fn BlogPost(cx: Scope, post: String) -> Element {
log::debug!("rendering blog post {}", post);
render! {
div {
h3 { "blog post: {post}" }
Link { target: Route::BlogList {}, "back to blog list" }
Link { to: Route::BlogList {}, "back to blog list" }
}
}
}
#[inline_props]
#[component]
fn Oranges(cx: Scope) -> Element {
render!("Oranges are not apples!")
}
+42
View File
@@ -0,0 +1,42 @@
#![allow(non_snake_case)]
use dioxus::prelude::*;
use dioxus_router::prelude::*;
#[derive(Routable, Clone, PartialEq)]
enum Route {
#[layout(Nav)]
#[route("/")]
Homepage {},
#[route("/blog/:id")]
Blog { id: String },
}
#[component]
fn Homepage(cx: Scope) -> Element {
render! { h1 { "Welcome home" } }
}
#[component]
fn Blog(cx: Scope, id: String) -> Element {
render! {
h1 { "How to make: " }
p { "{id}" }
}
}
#[component]
fn Nav(cx: Scope) -> Element {
render! {
nav {
li { Link { to: Route::Homepage { }, "Go home" } }
li { Link { to: Route::Blog { id: "Brownies".to_string() }, "Learn Brownies" } }
li { Link { to: Route::Blog { id: "Cookies".to_string() }, "Learn Cookies" } }
}
div { Outlet::<Route> {} }
}
}
fn main() {
dioxus_desktop::launch(|cx| render!(Router::<Route> {}));
}
+1 -1
View File
@@ -10,7 +10,7 @@
//! will cause it to fetch a random dog image from the Dog API. Since the data
//! is not ready immediately, we render some loading text.
//!
//! We can achieve the majoirty of suspense functionality by composing "suspenseful"
//! We can achieve the majority of suspense functionality by composing "suspenseful"
//! primitives in our own custom components.
use dioxus::prelude::*;
+1 -1
View File
@@ -30,7 +30,7 @@ watch_path = ["src", "public"]
[web.resource]
# CSS style file
style = ["tailwind.css"]
style = ["/tailwind.css"]
# Javascript code file
script = []
+1 -1
View File
@@ -81,7 +81,7 @@ watch_path = ["src", "public"]
[web.resource]
# CSS style file
style = ["tailwind.css"]
style = ["/tailwind.css"]
# Javascript code file
script = []