├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── Cargo.toml
├── Dioxus.toml
├── LICENSE
├── README.md
├── README.zh-CN.md
├── index.html
├── public
├── CNAME
├── assets
│ ├── dioxus.png
│ └── tailwind
│ │ ├── tailwind.config.js
│ │ └── tailwind.min.js
├── favicon.ico
└── robots.txt
├── settings.json
└── src
├── components
├── content.rs
├── footer.rs
└── mod.rs
├── hooks
├── markdown.rs
├── mod.rs
└── mode.rs
├── main.rs
├── markdown
└── readme.md
└── pages
├── _404.rs
├── mod.rs
└── starter.rs
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: github pages
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | build-deploy:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: "Dioxus Deploy"
13 | uses: DioxusLabs/deploy-action@v1
14 | with:
15 | toolSource: "mrxiaozhuox/dioxus-cli"
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | /target/
4 |
5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
7 | Cargo.lock
8 |
9 | # These are backup files generated by rustfmt
10 | **/*.rs.bk
11 |
12 | # System file
13 | .DS_Store
14 |
15 | # Add by dioxus
16 | /dist/
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "dioxus-starter"
3 | version = "0.2.0"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 |
8 | [dependencies]
9 | dioxus = { version = "0.5.6", features = ["web", "router"] }
10 | fermi = "0.4.3"
11 |
12 | js-sys = "0.3.58"
13 | web-sys = { version = "0.3.58", features = ["Storage"] }
14 | dioxus-free-icons = { version = "0.8.6", features = ["font-awesome-brands", "font-awesome-solid" ] }
15 | dioxus-toast = { version = "0.4.0", default-features = false, features = ["web"] }
16 | gloo = "0.8.0"
17 | log = "0.4.6"
18 | wasm-logger = "0.2.0"
19 | anyhow = "1.0.57"
20 | urlencoding = "2.1.0"
21 | pulldown-cmark = "0.9.1"
22 |
23 | # dioxus-sdk = { version = "0.5", features = ["storage"] }
24 | dioxus-sdk = { git = "https://github.com/DioxusLabs/sdk/", features = ["storage"] }
25 |
26 |
--------------------------------------------------------------------------------
/Dioxus.toml:
--------------------------------------------------------------------------------
1 | [application]
2 |
3 | # dioxus project name
4 | name = "dioxus-starter"
5 |
6 | # default platfrom
7 | # you can also use `dioxus serve/build --platform XXX` to use other platform
8 | # value: web | desktop
9 | default_platform = "web"
10 |
11 | # Web `build` & `serve` dist path
12 | out_dir = "dist"
13 |
14 | # resource (static) file folder
15 | asset_dir = "public"
16 |
17 | [web.app]
18 |
19 | # HTML title tag content
20 | title = "Dioxus Starter | opinionated dioxus template"
21 |
22 | [web.watcher]
23 |
24 | watch_path = [
25 | "src",
26 | "public",
27 | "Dioxus.toml",
28 | ]
29 |
30 | index_on_404 = true
31 |
32 | # include `assets` in web platform
33 | [web.resource]
34 |
35 | # CSS style file
36 | style = []
37 |
38 | # Javascript code file
39 | script = [
40 | "/assets/tailwind/tailwind.min.js",
41 | "/assets/tailwind/tailwind.config.js",
42 | ]
43 |
44 | [web.resource.dev]
45 |
46 | # Javascript code file
47 | # serve: [dev-server] only
48 | script = []
49 |
50 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 YuKun Liu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
Dioxus Starter
3 |
4 |
5 |
8 |
9 |
10 |
11 | English
12 | |
13 | 简体中文
14 |
15 |
16 |
17 | ## Features
18 |
19 | - 🧭 [Dynamic routing](https://dioxuslabs.com/nightly/router/) support
20 | - ☀️ Light / Dark mode support
21 | - 🏡 [Tailwind](https://tailwindcss.com/) framework support
22 | - 📙 Markdown parser support
23 | - 🍿 [Toast](https://github.com/mrxiaozhuox/dioxus-toast) popup support
24 | - 💎 [FA](https://fontawesome.com/) free icon support
25 |
26 | ## Pre-Packed
27 |
28 | ### UI Framework
29 |
30 | - [Tailwind](https://github.com/tailwindlabs/tailwindcss) - A utility-first CSS framework
31 |
32 | ### Dioxus Plugins
33 |
34 | - [Dioxus Router](https://github.com/DioxusLabs/dioxus/tree/master/packages/router) - Dioxus Router is a first-party router for Dioxus
35 | - [Dioxus Fermi](https://github.com/DioxusLabs/dioxus/tree/master/packages/fermi) - Atom-based global state management solution for Dioxus
36 | - [Dioxus Free Icon](https://github.com/nissy-dev/dioxus-free-icons) - Use free svg icons in your Dioxus
37 | - [Dioxus Toast](https://github.com/mrxiaozhuox/dioxus-toast) - Add toast support for your Dioxus
38 | - [Dioxus Local torage](https://github.com/mrxiaozhuox/dioxus-local-storage) - Add Storage Hooks for Dioxus
39 |
40 | ## Try it
41 |
42 | ```
43 | dx create --template=gh:mrxiaozhuox/dioxus-starter
44 | cd {PROJECT_NAME}
45 | dx serve
46 | ```
47 |
--------------------------------------------------------------------------------
/README.zh-CN.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrxiaozhuox/dioxus-starter/57d0d9a7fb3e02b81de87bdb5b60b57e9c2e76df/README.zh-CN.md
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {app_title}
5 |
6 |
7 |
8 |
9 | {style_include}
10 |
11 |
12 |
13 |
14 |
22 | {script_include}
23 |
24 |
--------------------------------------------------------------------------------
/public/CNAME:
--------------------------------------------------------------------------------
1 | dioxus-starter.mrxzx.info
--------------------------------------------------------------------------------
/public/assets/dioxus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrxiaozhuox/dioxus-starter/57d0d9a7fb3e02b81de87bdb5b60b57e9c2e76df/public/assets/dioxus.png
--------------------------------------------------------------------------------
/public/assets/tailwind/tailwind.config.js:
--------------------------------------------------------------------------------
1 | tailwind.config = {
2 | darkMode: "class"
3 | }
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrxiaozhuox/dioxus-starter/57d0d9a7fb3e02b81de87bdb5b60b57e9c2e76df/public/favicon.ico
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Allow: /
--------------------------------------------------------------------------------
/settings.json:
--------------------------------------------------------------------------------
1 | {"Lua.diagnostics.globals":["library_dir"],"Lua.workspace.library":["../core/"]}
--------------------------------------------------------------------------------
/src/components/content.rs:
--------------------------------------------------------------------------------
1 | use dioxus::prelude::*;
2 | use pulldown_cmark::Parser;
3 |
4 | #[component]
5 | pub fn Href(to: ReadOnlySignal, children: Element) -> Element {
6 | rsx! {
7 | a { class: "text-cyan-700 dark:text-cyan-100 underline", href: "{to}", target: "_blank", { children } }
8 | }
9 | }
10 |
11 | #[derive(Props, PartialEq, Clone)]
12 | pub struct MarkdownProps {
13 | #[props(default)]
14 | class: ReadOnlySignal,
15 | content: String,
16 | }
17 |
18 | #[component]
19 | pub fn Markdown(props: MarkdownProps) -> Element {
20 | let content = &props.content;
21 | let parser = Parser::new(content);
22 | let mut html_buf = String::new();
23 | pulldown_cmark::html::push_html(&mut html_buf, parser);
24 | let extra_class = &props.class;
25 | rsx! {div { id: "markdown-body", class: "prose {extra_class}", dangerous_inner_html: "{html_buf}" }}
26 | }
27 |
--------------------------------------------------------------------------------
/src/components/footer.rs:
--------------------------------------------------------------------------------
1 | use crate::hooks::mode::{mode, use_mode};
2 | use dioxus::prelude::*;
3 | use dioxus_free_icons::{
4 | icons::{fa_brands_icons, fa_solid_icons},
5 | Icon,
6 | };
7 |
8 | pub fn Footer() -> Element {
9 | let mut current_mode = use_mode();
10 | rsx! {
11 | div { class: "mt-6 flex space-x-4 justify-center",
12 | Link {
13 | class: "text-black dark:text-white hover:text-gray-800 dark:hover:text-gray-200",
14 | to: "/",
15 | Icon { height: 26, width: 26, icon: fa_solid_icons::FaHouse }
16 | }
17 | a {
18 | class: "text-black dark:text-white hover:text-gray-800 dark:hover:text-gray-200",
19 | href: "javascript:;",
20 | onclick: move |_| {
21 | let is_dark = !current_mode.read().clone();
22 | // current_mode.set(dark);
23 | *current_mode.write() = is_dark;
24 | mode(is_dark);
25 | },
26 | if current_mode.read().clone() {
27 | Icon {
28 | height: 26,
29 | width: 26,
30 | icon: fa_solid_icons::FaSun
31 | }
32 | } else {
33 | Icon {
34 | height: 26,
35 | width: 26,
36 | icon: fa_solid_icons::FaMoon
37 | }
38 | }
39 | }
40 | Link {
41 | class: "text-black dark:text-white hover:text-gray-800 dark:hover:text-gray-200",
42 | to: "/about",
43 | Icon { height: 26, width: 26, icon: fa_solid_icons::FaBook }
44 | }
45 | a {
46 | class: "text-black dark:text-white hover:text-gray-800 dark:hover:text-gray-200",
47 | href: "https://github.com/mrxiaozhuox/dioxus-starter",
48 | Icon { height: 26, width: 26, icon: fa_brands_icons::FaGithub }
49 | }
50 | }
51 | div { class: "mt-10 flex justify-center text-gray-400",
52 | span {
53 | "[ made by "
54 | a {
55 | class: "underline",
56 | href: "https://github.com/mrxiaozhuox/",
57 | target: "_blank",
58 | "@mrxiaozhuox"
59 | }
60 | " ]"
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/components/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod footer;
2 | pub mod content;
--------------------------------------------------------------------------------
/src/hooks/markdown.rs:
--------------------------------------------------------------------------------
1 | // use dioxus::prelude::use_hook;
2 | // use pulldown_cmark::{Options, Parser, html};
3 | //
4 | // pub fn use_markdown() -> UseMarkdown<'_, '_> {
5 | // let options = Options::all();
6 | // use_hook(|| {
7 | // let parser = Parser::new_ext(str, options);
8 | // UseMarkdown { parser }
9 | // })
10 | // }
11 | //
12 | // pub struct UseMarkdown<'a, 'b> {
13 | // parser: Parser<'a, 'b>
14 | // }
15 | //
16 | // impl<'a, 'b> UseMarkdown<'a, 'b> {
17 | // pub fn to_html(&mut self) -> String {
18 | // let mut output = String::new();
19 | // html::push_html(&mut output, &mut self.parser);
20 | // output
21 | // }
22 | // }
23 |
--------------------------------------------------------------------------------
/src/hooks/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod mode;
2 | pub mod markdown;
--------------------------------------------------------------------------------
/src/hooks/mode.rs:
--------------------------------------------------------------------------------
1 | use dioxus::signals::{Readable, Signal};
2 | use dioxus_sdk::storage::{use_synced_storage, LocalStorage};
3 |
4 | pub fn use_mode() -> Signal {
5 | use_synced_storage::("mode".to_string(), || false)
6 | }
7 |
8 | pub fn mode(dark: bool) {
9 | if dark {
10 | let _ = js_sys::eval("document.documentElement.classList.add('dark');");
11 | } else {
12 | let _ = js_sys::eval("document.documentElement.classList.remove('dark');");
13 | }
14 | }
15 |
16 | pub fn init_mode_info() {
17 | let _ = js_sys::eval("document.body.classList.add('dark:bg-gray-600');");
18 | let dark = use_mode();
19 | if *dark.read() {
20 | let _ = js_sys::eval("document.documentElement.classList.add('dark');");
21 | } else {
22 | let _ = js_sys::eval("document.documentElement.classList.remove('dark');");
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main.rs:
--------------------------------------------------------------------------------
1 | #![allow(non_snake_case)]
2 |
3 | use dioxus::prelude::*;
4 | use dioxus_toast::{ToastFrame, ToastManager};
5 |
6 | mod components;
7 | mod hooks;
8 | mod pages;
9 |
10 | use hooks::mode::init_mode_info;
11 | use pages::_404::NotFound;
12 | use pages::starter::{About, HelloDioxus, SayHi};
13 |
14 | #[derive(Routable, Clone, Debug, PartialEq)]
15 | enum Route {
16 | // Main Page
17 | #[route("/")]
18 | HelloDioxus {},
19 |
20 | // Say Hi Page
21 | #[route("/hi/:name")]
22 | SayHi { name: String },
23 |
24 | // About Page
25 | #[route("/about")]
26 | About {},
27 |
28 | // 404 Not Found Page
29 | #[route("/:route")]
30 | NotFound { route: String },
31 | }
32 |
33 | fn main() {
34 |
35 | wasm_logger::init(wasm_logger::Config::default());
36 |
37 | dioxus_sdk::storage::set_dir!();
38 |
39 | log::info!("Dioxus Starter: https://github.com/mrxiaozhuox/dioxus-starter");
40 | launch(App)
41 | }
42 |
43 | fn App() -> Element {
44 | // init mode information
45 | init_mode_info();
46 |
47 | let toast = use_context_provider(|| Signal::new(ToastManager::default()));
48 |
49 | rsx! {
50 | // dioxus toast manager init
51 | ToastFrame { manager: toast }
52 | Router:: {}
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/markdown/readme.md:
--------------------------------------------------------------------------------
1 |
2 |
🔮 Dioxus Starter 🔮
3 |
4 |
5 |
9 |
10 | ## Features
11 | - 🧭 [Dynamic routing](https://dioxuslabs.com/nightly/router/) support
12 | - ☀️ Light / Dark mode support
13 | - 🏡 [Tailwind](https://tailwindcss.com/) framework support
14 | - 📙 Markdown parser support
15 | - 🍿 [Toast](https://github.com/mrxiaozhuox/dioxus-toast) popup support
16 | - 💎 [FA](https://fontawesome.com/) free icon support
17 |
18 | > This page display from markdown file.
--------------------------------------------------------------------------------
/src/pages/_404.rs:
--------------------------------------------------------------------------------
1 | use dioxus::prelude::*;
2 |
3 | use crate::components::footer::Footer;
4 |
5 | #[component]
6 | pub fn NotFound(route: String) -> Element {
7 | rsx! {
8 | section { class: "h-screen bg-cover bg-white dark:bg-gray-600",
9 | div { class: "flex h-full w-full items-center justify-center container mx-auto px-8",
10 | div { class: "max-w-2xl text-center",
11 | h1 { class: "text-3xl sm:text-5xl capitalize tracking-widest dark:text-white lg:text-6xl",
12 | "Page Not Found"
13 | }
14 | Footer {}
15 | }
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/pages/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod _404;
2 | pub mod starter;
3 |
4 |
--------------------------------------------------------------------------------
/src/pages/starter.rs:
--------------------------------------------------------------------------------
1 | use dioxus::prelude::*;
2 | use dioxus_toast::{ToastInfo, ToastManager};
3 | use crate::components::{content::Markdown, footer::Footer};
4 |
5 | #[component]
6 | pub fn HelloDioxus() -> Element {
7 | let mut input_name = use_signal(String::new);
8 | let router = use_navigator();
9 | let mut toast: Signal = use_context();
10 | rsx! {
11 | section { class: "h-screen bg-cover bg-white dark:bg-gray-600",
12 | div { class: "flex h-full w-full items-center justify-center container mx-auto px-8",
13 | div { class: "max-w-2xl text-center",
14 | h1 { class: "text-3xl sm:text-5xl capitalize tracking-widest text-gray-600 dark:text-white lg:text-6xl",
15 | "Dioxus Starter"
16 | }
17 | p { class: "mt-6 lg:text-lg text-gray-600 dark:text-white",
18 | "Opinionated Dioxus Starter Template"
19 | }
20 | div { class: "mt-8 flex flex-col space-y-3 sm:-mx-2 sm:flex-row sm:justify-center sm:space-y-0",
21 | input {
22 | r#type: "text",
23 | class: "rounded-md border border-transparent bg-gray-800 dark:bg-white/20 px-4 py-2 text-white placeholder-white backdrop-blur-sm focus:border-blue-400 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-40 sm:mx-2",
24 | placeholder: "What's your name ?",
25 | oninput: move |e| input_name.set(e.value().clone()),
26 | value: "{input_name}"
27 | }
28 | button {
29 | id: "submit-button",
30 | class: "transform rounded-md bg-blue-700 px-8 py-2 text-sm font-medium capitalize tracking-wide text-white transition-colors duration-200 hover:bg-blue-600 focus:bg-blue-600 focus:outline-none sm:mx-2",
31 | onclick: move |_| {
32 | let name = input_name.read();
33 | if !name.is_empty() {
34 | router.push(&format!("/hi/{}", name));
35 | } else {
36 | toast.write().popup(ToastInfo::warning("Empty input box", "Dioxus Toast"));
37 | }
38 | },
39 | "Go"
40 | }
41 | }
42 | Footer {}
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
49 | #[component]
50 | pub fn SayHi(name: String) -> Element {
51 | let name = urlencoding::decode(&name).expect("UTF-8").to_string();
52 | rsx! {
53 | section { class: "h-screen bg-cover bg-white dark:bg-gray-600",
54 | div { class: "flex h-full w-full items-center justify-center container mx-auto px-8",
55 | div { class: "max-w-2xl text-center",
56 | h1 { class: "text-3xl sm:text-5xl capitalize tracking-widest dark:text-white lg:text-6xl",
57 | "Hi, "{name}""
58 | }
59 | Footer {}
60 | }
61 | }
62 | }
63 | }
64 | }
65 |
66 | #[component]
67 | pub fn About() -> Element {
68 | let content = include_str!("../markdown/readme.md");
69 | rsx! {
70 | div { class: "dark:bg-gray-600",
71 | br {}
72 | div { class: "md:flex md:justify-center",
73 | div { class: "block sm:p-6 md:p-8 rounded-lg shadow-2xl bg-white dark:bg-gray-700",
74 | Markdown { class: "dark:prose-invert", content: content.to_string() }
75 | }
76 | }
77 | Footer {}
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------