diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..80aab8e --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,7 @@ +# Generated by Cargo +# will have compiled files and executables +/target +.DS_Store + +# These are backup files generated by rustfmt +**/*.rs.bk diff --git a/app/Cargo.toml b/app/Cargo.toml new file mode 100644 index 0000000..53e040f --- /dev/null +++ b/app/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "app" +version = "0.1.0" +authors = ["steppy "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +dioxus = { version = "0.6.0", features = ["router", "fullstack"] } + +[features] +default = ["web"] +web = ["dioxus/web"] +desktop = ["dioxus/desktop"] +mobile = ["dioxus/mobile"] diff --git a/app/Dioxus.toml b/app/Dioxus.toml new file mode 100644 index 0000000..182899c --- /dev/null +++ b/app/Dioxus.toml @@ -0,0 +1,24 @@ +[application] + +# App (Project) Name +name = "app" + +[web.app] + +# HTML title tag content +title = "app" + +# include `assets` in web platform +[web.resource] + +# Additional CSS style files +style = [] + +# Additional JavaScript files +script = [] + +[web.resource.dev] + +# Javascript code file +# serve: [dev-server] only +script = [] diff --git a/app/README.md b/app/README.md new file mode 100644 index 0000000..eb3ab84 --- /dev/null +++ b/app/README.md @@ -0,0 +1,18 @@ +# Development + +Your new bare-bones project includes minimal organization with a single `main.rs` file and a few assets. + +### Serving Your App + +Run the following command in the root of your project to start developing with the default platform: + +```bash +dx serve --platform web +``` + +To run for a different platform, use the `--platform platform` flag. E.g. + +```bash +dx serve --platform desktop +``` + diff --git a/app/assets/favicon.ico b/app/assets/favicon.ico new file mode 100644 index 0000000..eed0c09 Binary files /dev/null and b/app/assets/favicon.ico differ diff --git a/app/assets/header.svg b/app/assets/header.svg new file mode 100644 index 0000000..3581419 --- /dev/null +++ b/app/assets/header.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/assets/main.css b/app/assets/main.css new file mode 100644 index 0000000..0a59527 --- /dev/null +++ b/app/assets/main.css @@ -0,0 +1,107 @@ +/* App-wide styling */ +body { + background-color: #0f1116; + color: #ffffff; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + margin: 20px; +} + +#hero { + margin: 0; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +#links { + width: 400px; + text-align: left; + font-size: x-large; + color: white; + display: flex; + flex-direction: column; +} + +#links a { + color: white; + text-decoration: none; + margin-top: 20px; + margin: 10px 0px; + border: white 1px solid; + border-radius: 5px; + padding: 10px; +} + +#links a:hover { + background-color: #1f1f1f; + cursor: pointer; +} + +#header { + max-width: 1200px; +} + +/* Navbar */ +#navbar { + display: flex; + flex-direction: row; +} + +#navbar a { + color: #ffffff; + margin-right: 20px; + text-decoration: none; + transition: color 0.2s ease; +} + +#navbar a:hover { + cursor: pointer; + color: #91a4d2; +} + +/* Blog page */ +#blog { + margin-top: 50px; +} + +#blog a { + color: #ffffff; + margin-top: 50px; +} + +/* Echo */ +#echo { + width: 360px; + margin-left: auto; + margin-right: auto; + margin-top: 50px; + background-color: #1e222d; + padding: 20px; + border-radius: 10px; +} + +#echo > h4 { + margin: 0px 0px 15px 0px; +} + + +#echo > input { + border: none; + border-bottom: 1px white solid; + background-color: transparent; + color: #ffffff; + transition: border-bottom-color 0.2s ease; + outline: none; + display: block; + padding: 0px 0px 5px 0px; + width: 100%; +} + +#echo > input:focus { + border-bottom-color: #6d85c6; +} + +#echo > p { + margin: 20px 0px 0px auto; +} \ No newline at end of file diff --git a/app/src/main.rs b/app/src/main.rs new file mode 100644 index 0000000..baf55d1 --- /dev/null +++ b/app/src/main.rs @@ -0,0 +1,133 @@ +use dioxus::prelude::*; + +#[derive(Debug, Clone, Routable, PartialEq)] +#[rustfmt::skip] +enum Route { + #[layout(Navbar)] + #[route("/")] + Home {}, + #[route("/blog/:id")] + Blog { id: i32 }, +} + +const FAVICON: Asset = asset!("/assets/favicon.ico"); +const MAIN_CSS: Asset = asset!("/assets/main.css"); +const HEADER_SVG: Asset = asset!("/assets/header.svg"); + +fn main() { + dioxus::launch(App); +} + +#[component] +fn App() -> Element { + rsx! { + document::Link { rel: "icon", href: FAVICON } + document::Link { rel: "stylesheet", href: MAIN_CSS } + Router:: {} + } +} + +#[component] +pub fn Hero() -> Element { + rsx! { + div { + id: "hero", + img { src: HEADER_SVG, id: "header" } + div { id: "links", + a { href: "https://dioxuslabs.com/learn/0.6/", "📚 Learn Dioxus" } + a { href: "https://dioxuslabs.com/awesome", "🚀 Awesome Dioxus" } + a { href: "https://github.com/dioxus-community/", "📡 Community Libraries" } + a { href: "https://github.com/DioxusLabs/sdk", "⚙️ Dioxus Development Kit" } + a { href: "https://marketplace.visualstudio.com/items?itemName=DioxusLabs.dioxus", "💫 VSCode Extension" } + a { href: "https://discord.gg/XgGxMSkvUM", "👋 Community Discord" } + } + } + } +} + +/// Home page +#[component] +fn Home() -> Element { + rsx! { + Hero {} + Echo {} + } +} + +/// Blog page +#[component] +pub fn Blog(id: i32) -> Element { + rsx! { + div { + id: "blog", + + // Content + h1 { "This is blog #{id}!" } + p { "In blog #{id}, we show how the Dioxus router works and how URL parameters can be passed as props to our route components." } + + // Navigation links + Link { + to: Route::Blog { id: id - 1 }, + "Previous" + } + span { " <---> " } + Link { + to: Route::Blog { id: id + 1 }, + "Next" + } + } + } +} + +/// Shared navbar component. +#[component] +fn Navbar() -> Element { + rsx! { + div { + id: "navbar", + Link { + to: Route::Home {}, + "Home" + } + Link { + to: Route::Blog { id: 1 }, + "Blog" + } + } + + Outlet:: {} + } +} + +/// Echo component that demonstrates fullstack server functions. +#[component] +fn Echo() -> Element { + let mut response = use_signal(|| String::new()); + + rsx! { + div { + id: "echo", + h4 { "ServerFn Echo" } + input { + placeholder: "Type here to echo...", + oninput: move |event| async move { + let data = echo_server(event.value()).await.unwrap(); + response.set(data); + }, + } + + if !response().is_empty() { + p { + "Server echoed: " + i { "{response}" } + } + } + } + } +} + +/// Echo the user input on the server. +#[server(EchoServer)] +async fn echo_server(input: String) -> Result { + Ok(input) +}