commit ee5c4f4638d033fc66151e382795b153f2f699ec Author: Amatsugu Date: Wed Jan 14 15:45:37 2026 -0500 project setup diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba36dcb --- /dev/null +++ b/.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/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a392306 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "azki" +version = "0.1.0" +authors = ["Amatsugu "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +dioxus = { version = "0.7.1", features = ["router"] } + +[features] +default = ["web"] +# The feature that are only required for the web = ["dioxus/web"] build target should be optional and only enabled in the web = ["dioxus/web"] feature +web = ["dioxus/web"] +# The feature that are only required for the desktop = ["dioxus/desktop"] build target should be optional and only enabled in the desktop = ["dioxus/desktop"] feature +desktop = ["dioxus/desktop"] +# The feature that are only required for the mobile = ["dioxus/mobile"] build target should be optional and only enabled in the mobile = ["dioxus/mobile"] feature +mobile = ["dioxus/mobile"] diff --git a/Dioxus.toml b/Dioxus.toml new file mode 100644 index 0000000..864befb --- /dev/null +++ b/Dioxus.toml @@ -0,0 +1,21 @@ +[application] + +[web.app] + +# HTML title tag content +title = "azki" + +# 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/README.md b/README.md new file mode 100644 index 0000000..c4796b2 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# Development + +Your new jumpstart project includes basic organization with an organized `assets` folder and a `components` folder. +If you chose to develop with the router feature, you will also have a `views` folder. + +``` +project/ +├─ assets/ # Any assets that are used by the app should be placed here +├─ src/ +│ ├─ main.rs # The entrypoint for the app. It also defines the routes for the app. +│ ├─ components/ +│ │ ├─ mod.rs # Defines the components module +│ │ ├─ hero.rs # The Hero component for use in the home page +│ ├─ views/ # The views each route will render in the app. +│ │ ├─ mod.rs # Defines the module for the views route and re-exports the components for each route +│ │ ├─ blog.rs # The component that will render at the /blog/:id route +│ │ ├─ home.rs # The component that will render at the / route +├─ Cargo.toml # The Cargo.toml file defines the dependencies and feature flags for your project +``` + + + +### Serving Your App + +Run the following command in the root of your project to start developing with the default platform: + +```bash +dx serve +``` + +To run for a different platform, use the `--platform platform` flag. E.g. +```bash +dx serve --platform desktop +``` + + diff --git a/assets/favicon.ico b/assets/favicon.ico new file mode 100644 index 0000000..eed0c09 Binary files /dev/null and b/assets/favicon.ico differ diff --git a/assets/header.svg b/assets/header.svg new file mode 100644 index 0000000..916daba --- /dev/null +++ b/assets/header.svg @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/assets/styling/blog.css b/assets/styling/blog.css new file mode 100644 index 0000000..03cf8d9 --- /dev/null +++ b/assets/styling/blog.css @@ -0,0 +1,8 @@ +#blog { + margin-top: 50px; +} + +#blog a { + color: #ffffff; + margin-top: 50px; +} \ No newline at end of file diff --git a/assets/styling/main.css b/assets/styling/main.css new file mode 100644 index 0000000..e9370eb --- /dev/null +++ b/assets/styling/main.css @@ -0,0 +1,42 @@ +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; +} \ No newline at end of file diff --git a/assets/styling/navbar.css b/assets/styling/navbar.css new file mode 100644 index 0000000..11a2f8f --- /dev/null +++ b/assets/styling/navbar.css @@ -0,0 +1,16 @@ +#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; +} \ No newline at end of file diff --git a/src/components/hero.rs b/src/components/hero.rs new file mode 100644 index 0000000..e3141e7 --- /dev/null +++ b/src/components/hero.rs @@ -0,0 +1,25 @@ +use dioxus::prelude::*; + +const HEADER_SVG: Asset = asset!("/assets/header.svg"); + +#[component] +pub fn Hero() -> Element { + rsx! { + // We can create elements inside the rsx macro with the element name followed by a block of attributes and children. + div { + // Attributes should be defined in the element before any children + id: "hero", + // After all attributes are defined, we can define child elements and components + img { src: HEADER_SVG, id: "header" } + div { id: "links", + // The RSX macro also supports text nodes surrounded by quotes + a { href: "https://dioxuslabs.com/learn/0.7/", "📚 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" } + } + } + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs new file mode 100644 index 0000000..402c19d --- /dev/null +++ b/src/components/mod.rs @@ -0,0 +1,6 @@ +//! The components module contains all shared components for our app. Components are the building blocks of dioxus apps. +//! They can be used to defined common UI elements like buttons, forms, and modals. In this template, we define a Hero +//! component to be used in our app. + +mod hero; +pub use hero::Hero; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..658028b --- /dev/null +++ b/src/main.rs @@ -0,0 +1,66 @@ +// The dioxus prelude contains a ton of common items used in dioxus apps. It's a good idea to import wherever you +// need dioxus +use dioxus::prelude::*; + +use components::Hero; +use views::{Blog, Home, Navbar}; + +/// Define a components module that contains all shared components for our app. +mod components; +/// Define a views module that contains the UI for all Layouts and Routes for our app. +mod views; + +/// The Route enum is used to define the structure of internal routes in our app. All route enums need to derive +/// the [`Routable`] trait, which provides the necessary methods for the router to work. +/// +/// Each variant represents a different URL pattern that can be matched by the router. If that pattern is matched, +/// the components for that route will be rendered. +#[derive(Debug, Clone, Routable, PartialEq)] +#[rustfmt::skip] +enum Route { + // The layout attribute defines a wrapper for all routes under the layout. Layouts are great for wrapping + // many routes with a common UI like a navbar. + #[layout(Navbar)] + // The route attribute defines the URL pattern that a specific route matches. If that pattern matches the URL, + // the component for that route will be rendered. The component name that is rendered defaults to the variant name. + #[route("/")] + Home {}, + // The route attribute can include dynamic parameters that implement [`std::str::FromStr`] and [`std::fmt::Display`] with the `:` syntax. + // In this case, id will match any integer like `/blog/123` or `/blog/-456`. + #[route("/blog/:id")] + // Fields of the route variant will be passed to the component as props. In this case, the blog component must accept + // an `id` prop of type `i32`. + Blog { id: i32 }, +} + +// We can import assets in dioxus with the `asset!` macro. This macro takes a path to an asset relative to the crate root. +// The macro returns an `Asset` type that will display as the path to the asset in the browser or a local path in desktop bundles. +const FAVICON: Asset = asset!("/assets/favicon.ico"); +// The asset macro also minifies some assets like CSS and JS to make bundled smaller +const MAIN_CSS: Asset = asset!("/assets/styling/main.css"); + +fn main() { + // The `launch` function is the main entry point for a dioxus app. It takes a component and renders it with the platform feature + // you have enabled + dioxus::launch(App); +} + +/// App is the main component of our app. Components are the building blocks of dioxus apps. Each component is a function +/// that takes some props and returns an Element. In this case, App takes no props because it is the root of our app. +/// +/// Components should be annotated with `#[component]` to support props, better error messages, and autocomplete +#[component] +fn App() -> Element { + // The `rsx!` macro lets us define HTML inside of rust. It expands to an Element with all of our HTML inside. + rsx! { + // In addition to element and text (which we will see later), rsx can contain other components. In this case, + // we are using the `document::Link` component to add a link to our favicon and main CSS file into the head of our app. + document::Link { rel: "icon", href: FAVICON } + document::Link { rel: "stylesheet", href: MAIN_CSS } + + + // The router component renders the route enum we defined above. It will handle synchronization of the URL and render + // the layouts and components for the active route. + Router:: {} + } +} diff --git a/src/views/blog.rs b/src/views/blog.rs new file mode 100644 index 0000000..8e79bc6 --- /dev/null +++ b/src/views/blog.rs @@ -0,0 +1,39 @@ +use crate::Route; +use dioxus::prelude::*; + +const BLOG_CSS: Asset = asset!("/assets/styling/blog.css"); + +/// The Blog page component that will be rendered when the current route is `[Route::Blog]` +/// +/// The component takes a `id` prop of type `i32` from the route enum. Whenever the id changes, the component function will be +/// re-run and the rendered HTML will be updated. +#[component] +pub fn Blog(id: i32) -> Element { + rsx! { + document::Link { rel: "stylesheet", href: BLOG_CSS } + + 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 + // The `Link` component lets us link to other routes inside our app. It takes a `to` prop of type `Route` and + // any number of child nodes. + Link { + // The `to` prop is the route that the link should navigate to. We can use the `Route` enum to link to the + // blog page with the id of -1. Since we are using an enum instead of a string, all of the routes will be checked + // at compile time to make sure they are valid. + to: Route::Blog { id: id - 1 }, + "Previous" + } + span { " <---> " } + Link { + to: Route::Blog { id: id + 1 }, + "Next" + } + } + } +} diff --git a/src/views/home.rs b/src/views/home.rs new file mode 100644 index 0000000..b519c1b --- /dev/null +++ b/src/views/home.rs @@ -0,0 +1,11 @@ +use crate::components::Hero; +use dioxus::prelude::*; + +/// The Home page component that will be rendered when the current route is `[Route::Home]` +#[component] +pub fn Home() -> Element { + rsx! { + Hero {} + + } +} diff --git a/src/views/mod.rs b/src/views/mod.rs new file mode 100644 index 0000000..0a41003 --- /dev/null +++ b/src/views/mod.rs @@ -0,0 +1,18 @@ +//! The views module contains the components for all Layouts and Routes for our app. Each layout and route in our [`Route`] +//! enum will render one of these components. +//! +//! +//! The [`Home`] and [`Blog`] components will be rendered when the current route is [`Route::Home`] or [`Route::Blog`] respectively. +//! +//! +//! The [`Navbar`] component will be rendered on all pages of our app since every page is under the layout. The layout defines +//! a common wrapper around all child routes. + +mod home; +pub use home::Home; + +mod blog; +pub use blog::Blog; + +mod navbar; +pub use navbar::Navbar; diff --git a/src/views/navbar.rs b/src/views/navbar.rs new file mode 100644 index 0000000..6a68b37 --- /dev/null +++ b/src/views/navbar.rs @@ -0,0 +1,32 @@ +use crate::Route; +use dioxus::prelude::*; + +const NAVBAR_CSS: Asset = asset!("/assets/styling/navbar.css"); + +/// The Navbar component that will be rendered on all pages of our app since every page is under the layout. +/// +/// +/// This layout component wraps the UI of [Route::Home] and [Route::Blog] in a common navbar. The contents of the Home and Blog +/// routes will be rendered under the outlet inside this component +#[component] +pub fn Navbar() -> Element { + rsx! { + document::Link { rel: "stylesheet", href: NAVBAR_CSS } + + div { + id: "navbar", + Link { + to: Route::Home {}, + "Home" + } + Link { + to: Route::Blog { id: 1 }, + "Blog" + } + } + + // The `Outlet` component is used to render the next component inside the layout. In this case, it will render either + // the [`Home`] or [`Blog`] component depending on the current route. + Outlet:: {} + } +}