Layout Components
First up, we're going to craft some general layout components for our app. This is a nice, gentle introduction to creating components, and we'll also get some reusable pieces out of it. We're going to create:
Header
componentFooter
component- We'll also tweak the
App
component to incorporate these new components
Components Folder
Time to get our code all nice and organized! We're going to make a components
folder in our src
directory. This is where we'll store all of our components. This way, we can easily import them into our main.rs
file. Neat, right?
If you want to get a deeper understanding of how to structure your code within a Rust project, the Rust Lang book has a fantastic section on it called Managing Growing Projects with Packages, Crates, and Modules. Definitely worth checking out!
Here's what our new structure will look like:
└── src # Source code
├── components # Components folder
│ ├── mod.rs # Components module
│ ├── footer.rs # Footer component
│ └── header.rs # Header component
And let's take a peek at what our mod.rs
file should look like:
#![allow(unused)] fn main() { mod footer; mod header; pub use footer::Footer; pub use header::Header; }
We've got our mod.rs
pulling double duty here. First, it's declaring our footer
and header
modules. Then, it's making Footer
and Header
available for other modules to use. This sets us up nicely for using these components in our main.rs
file.
Header Component
Alright, let's start with the Header
component. For now, we're keeping it simple, just displaying our app's title and a logo.
Whenever you're building a new component or working in our main.rs
file, remember to import dioxus::prelude::*
. It gives you access to all the macros and functions you need.
front/src/components/header.rs
#![allow(unused)] fn main() { use dioxus::prelude::*; pub fn Header(cx: Scope) -> Element { cx.render(rsx!( header { class: "sticky top-0 z-10 text-gray-400 bg-blue-300 body-font shadow-md", div { class: "container mx-auto flex flex-wrap p-0 flex-col md:flex-row justify-between items-center", a { class: "flex title-font font-medium items-center text-teal-950 mb-4 md:mb-0", img { class: "bg-transparent p-2 animate-jump", alt: "ferris", src: "ferris.png", "loading": "lazy" } span { class: "ml-3 text-2xl", "Rusty films"} } } } )) } }
Footer Component
Next up, we're going to build the Footer
component. This one's pretty straightforward – we're just going to stick a couple of images at the bottom of our app.
front/src/components/footer.rs
#![allow(unused)] fn main() { use dioxus::prelude::*; pub fn Footer(cx: Scope) -> Element { cx.render(rsx!( footer { class: "bg-blue-200 w-full h-16 p-2 box-border gap-6 flex flex-row justify-center items-center text-teal-950", a { class: "w-auto h-full", href: "https://www.devbcn.com/", target: "_blank", img { class: "h-full w-auto", alt: "DevBcn", src: "devbcn.png", "loading": "lazy" } } svg { fill: "none", view_box: "0 0 24 24", stroke_width: "1.5", stroke: "currentColor", class: "w-6 h-6", path { stroke_linecap: "round", stroke_linejoin: "round", d: "M6 18L18 6M6 6l12 12" } } a { class: "w-auto h-full", href: "https://www.meetup.com/es-ES/bcnrust/", target: "_blank", img { class: "h-full w-auto", alt: "BcnRust", src: "bcnrust.png", "loading": "lazy" } } } )) } }
Just like we did with the Header
component, remember to import dioxus::prelude::*
to have access to all the macros and functions we need. And feel free to change up the Tailwind classes to fit your design.
Now, we've got a Header
and Footer
ready to roll. Next, let's update our App
component to use these new elements.
front/src/main.rs
#![allow(non_snake_case)]
// Import the Dioxus prelude to gain access to the `rsx!` macro and the `Scope` and `Element` types.
+mod components;
+use components::{Footer, Header};
use dioxus::prelude::*;
fn main() {
// Launch the web application using the App component as the root.
dioxus_web::launch(App);
}
// Define a component that renders a div with the text "Hello, world!"
fn App(cx: Scope) -> Element {
cx.render(rsx! {
- div {
- "Hello, world!"
- }
+ main {
+ class: "relative z-0 bg-blue-100 w-screen h-auto min-h-screen flex flex-col justify-start items-stretch",
+ Header {}
+ section {
+ class: "md:container md:mx-auto md:py-8 flex-1",
+ }
+ Footer {}
+ }
})
}