···11+# Generated by Cargo
22+# will have compiled files and executables
33+/target
44+.DS_Store
55+66+# These are backup files generated by rustfmt
77+**/*.rs.bk
+265
crates/tala/AGENTS.md
···11+You are an expert [0.7 Dioxus](https://dioxuslabs.com/learn/0.7) assistant. Dioxus 0.7 changes every api in dioxus. Only use this up to date documentation. `cx`, `Scope`, and `use_state` are gone
22+33+Provide concise code examples with detailed descriptions
44+55+# Dioxus Dependency
66+77+You can add Dioxus to your `Cargo.toml` like this:
88+99+```toml
1010+[dependencies]
1111+dioxus = { version = "0.7.1" }
1212+1313+[features]
1414+default = ["web", "webview", "server"]
1515+web = ["dioxus/web"]
1616+webview = ["dioxus/desktop"]
1717+server = ["dioxus/server"]
1818+```
1919+2020+# Launching your application
2121+2222+You need to create a main function that sets up the Dioxus runtime and mounts your root component.
2323+2424+```rust
2525+use dioxus::prelude::*;
2626+2727+fn main() {
2828+ dioxus::launch(App);
2929+}
3030+3131+#[component]
3232+fn App() -> Element {
3333+ rsx! { "Hello, Dioxus!" }
3434+}
3535+```
3636+3737+Then serve with `dx serve`:
3838+3939+```sh
4040+curl -sSL http://dioxus.dev/install.sh | sh
4141+dx serve
4242+```
4343+4444+# UI with RSX
4545+4646+```rust
4747+rsx! {
4848+ div {
4949+ class: "container", // Attribute
5050+ color: "red", // Inline styles
5151+ width: if condition { "100%" }, // Conditional attributes
5252+ "Hello, Dioxus!"
5353+ }
5454+ // Prefer loops over iterators
5555+ for i in 0..5 {
5656+ div { "{i}" } // use elements or components directly in loops
5757+ }
5858+ if condition {
5959+ div { "Condition is true!" } // use elements or components directly in conditionals
6060+ }
6161+6262+ {children} // Expressions are wrapped in brace
6363+ {(0..5).map(|i| rsx! { span { "Item {i}" } })} // Iterators must be wrapped in braces
6464+}
6565+```
6666+6767+# Assets
6868+6969+The asset macro can be used to link to local files to use in your project. All links start with `/` and are relative to the root of your project.
7070+7171+```rust
7272+rsx! {
7373+ img {
7474+ src: asset!("/assets/image.png"),
7575+ alt: "An image",
7676+ }
7777+}
7878+```
7979+8080+## Styles
8181+8282+The `document::Stylesheet` component will inject the stylesheet into the `<head>` of the document
8383+8484+```rust
8585+rsx! {
8686+ document::Stylesheet {
8787+ href: asset!("/assets/styles.css"),
8888+ }
8989+}
9090+```
9191+9292+# Components
9393+9494+Components are the building blocks of apps
9595+9696+* Component are functions annotated with the `#[component]` macro.
9797+* The function name must start with a capital letter or contain an underscore.
9898+* A component re-renders only under two conditions:
9999+ 1. Its props change (as determined by `PartialEq`).
100100+ 2. An internal reactive state it depends on is updated.
101101+102102+```rust
103103+#[component]
104104+fn Input(mut value: Signal<String>) -> Element {
105105+ rsx! {
106106+ input {
107107+ value,
108108+ oninput: move |e| {
109109+ *value.write() = e.value();
110110+ },
111111+ onkeydown: move |e| {
112112+ if e.key() == Key::Enter {
113113+ value.write().clear();
114114+ }
115115+ },
116116+ }
117117+ }
118118+}
119119+```
120120+121121+Each component accepts function arguments (props)
122122+123123+* Props must be owned values, not references. Use `String` and `Vec<T>` instead of `&str` or `&[T]`.
124124+* Props must implement `PartialEq` and `Clone`.
125125+* To make props reactive and copy, you can wrap the type in `ReadOnlySignal`. Any reactive state like memos and resources that read `ReadOnlySignal` props will automatically re-run when the prop changes.
126126+127127+# State
128128+129129+A signal is a wrapper around a value that automatically tracks where it's read and written. Changing a signal's value causes code that relies on the signal to rerun.
130130+131131+## Local State
132132+133133+The `use_signal` hook creates state that is local to a single component. You can call the signal like a function (e.g. `my_signal()`) to clone the value, or use `.read()` to get a reference. `.write()` gets a mutable reference to the value.
134134+135135+Use `use_memo` to create a memoized value that recalculates when its dependencies change. Memos are useful for expensive calculations that you don't want to repeat unnecessarily.
136136+137137+```rust
138138+#[component]
139139+fn Counter() -> Element {
140140+ let mut count = use_signal(|| 0);
141141+ let mut doubled = use_memo(move || count() * 2); // doubled will re-run when count changes because it reads the signal
142142+143143+ rsx! {
144144+ h1 { "Count: {count}" } // Counter will re-render when count changes because it reads the signal
145145+ h2 { "Doubled: {doubled}" }
146146+ button {
147147+ onclick: move |_| *count.write() += 1, // Writing to the signal rerenders Counter
148148+ "Increment"
149149+ }
150150+ button {
151151+ onclick: move |_| count.with_mut(|count| *count += 1), // use with_mut to mutate the signal
152152+ "Increment with with_mut"
153153+ }
154154+ }
155155+}
156156+```
157157+158158+## Context API
159159+160160+The Context API allows you to share state down the component tree. A parent provides the state using `use_context_provider`, and any child can access it with `use_context`
161161+162162+```rust
163163+#[component]
164164+fn App() -> Element {
165165+ let mut theme = use_signal(|| "light".to_string());
166166+ use_context_provider(|| theme); // Provide a type to children
167167+ rsx! { Child {} }
168168+}
169169+170170+#[component]
171171+fn Child() -> Element {
172172+ let theme = use_context::<Signal<String>>(); // Consume the same type
173173+ rsx! {
174174+ div {
175175+ "Current theme: {theme}"
176176+ }
177177+ }
178178+}
179179+```
180180+181181+# Async
182182+183183+For state that depends on an asynchronous operation (like a network request), Dioxus provides a hook called `use_resource`. This hook manages the lifecycle of the async task and provides the result to your component.
184184+185185+* The `use_resource` hook takes an `async` closure. It re-runs this closure whenever any signals it depends on (reads) are updated
186186+* The `Resource` object returned can be in several states when read:
187187+1. `None` if the resource is still loading
188188+2. `Some(value)` if the resource has successfully loaded
189189+190190+```rust
191191+let mut dog = use_resource(move || async move {
192192+ // api request
193193+});
194194+195195+match dog() {
196196+ Some(dog_info) => rsx! { Dog { dog_info } },
197197+ None => rsx! { "Loading..." },
198198+}
199199+```
200200+201201+# Routing
202202+203203+All possible routes are defined in a single Rust `enum` that derives `Routable`. Each variant represents a route and is annotated with `#[route("/path")]`. Dynamic Segments can capture parts of the URL path as parameters by using `:name` in the route string. These become fields in the enum variant.
204204+205205+The `Router<Route> {}` component is the entry point that manages rendering the correct component for the current URL.
206206+207207+You can use the `#[layout(NavBar)]` to create a layout shared between pages and place an `Outlet<Route> {}` inside your layout component. The child routes will be rendered in the outlet.
208208+209209+```rust
210210+#[derive(Routable, Clone, PartialEq)]
211211+enum Route {
212212+ #[layout(NavBar)] // This will use NavBar as the layout for all routes
213213+ #[route("/")]
214214+ Home {},
215215+ #[route("/blog/:id")] // Dynamic segment
216216+ BlogPost { id: i32 },
217217+}
218218+219219+#[component]
220220+fn NavBar() -> Element {
221221+ rsx! {
222222+ a { href: "/", "Home" }
223223+ Outlet<Route> {} // Renders Home or BlogPost
224224+ }
225225+}
226226+227227+#[component]
228228+fn App() -> Element {
229229+ rsx! { Router::<Route> {} }
230230+}
231231+```
232232+233233+```toml
234234+dioxus = { version = "0.7.1", features = ["router"] }
235235+```
236236+237237+# Fullstack
238238+239239+Fullstack enables server rendering and ipc calls. It uses Cargo features (`server` and a client feature like `web`) to split the code into a server and client binaries.
240240+241241+```toml
242242+dioxus = { version = "0.7.1", features = ["fullstack"] }
243243+```
244244+245245+## Server Functions
246246+247247+Use the `#[post]` / `#[get]` macros to define an `async` function that will only run on the server. On the server, this macro generates an API endpoint. On the client, it generates a function that makes an HTTP request to that endpoint.
248248+249249+```rust
250250+#[post("/api/double/:path/&query")]
251251+async fn double_server(number: i32, path: String, query: i32) -> Result<i32, ServerFnError> {
252252+ tokio::time::sleep(std::time::Duration::from_secs(1)).await;
253253+ Ok(number * 2)
254254+}
255255+```
256256+257257+## Hydration
258258+259259+Hydration is the process of making a server-rendered HTML page interactive on the client. The server sends the initial HTML, and then the client-side runs, attaches event listeners, and takes control of future rendering.
260260+261261+### Errors
262262+The initial UI rendered by the component on the client must be identical to the UI rendered on the server.
263263+264264+* Use the `use_server_future` hook instead of `use_resource`. It runs the future on the server, serializes the result, and sends it to the client, ensuring the client has the data immediately for its first render.
265265+* Any code that relies on browser-specific APIs (like accessing `localStorage`) must be run *after* hydration. Place this code inside a `use_effect` hook.
+16
crates/tala/Cargo.toml
···11+[package]
22+name = "tala"
33+version = "0.1.0"
44+authors = ["oscillatory.net <nick@oscillatory.net>"]
55+edition = "2021"
66+77+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88+99+[dependencies]
1010+dioxus = { version = "0.7.1", features = ["router"] }
1111+1212+[features]
1313+default = ["desktop"]
1414+web = ["dioxus/web"]
1515+desktop = ["dioxus/desktop"]
1616+mobile = ["dioxus/mobile"]
+21
crates/tala/Dioxus.toml
···11+[application]
22+33+[web.app]
44+55+# HTML title tag content
66+title = "tala"
77+88+# include `assets` in web platform
99+[web.resource]
1010+1111+# Additional CSS style files
1212+style = []
1313+1414+# Additional JavaScript files
1515+script = []
1616+1717+[web.resource.dev]
1818+1919+# Javascript code file
2020+# serve: [dev-server] only
2121+script = []
+50
crates/tala/README.md
···11+# Development
22+33+Your new bare-bones project includes minimal organization with a single `main.rs` file and a few assets.
44+55+```
66+project/
77+├─ assets/ # Any assets that are used by the app should be placed here
88+├─ src/
99+│ ├─ main.rs # main.rs is the entry point to your application and currently contains all components for the app
1010+├─ Cargo.toml # The Cargo.toml file defines the dependencies and feature flags for your project
1111+```
1212+1313+### Automatic Tailwind (Dioxus 0.7+)
1414+1515+As of Dioxus 0.7, there no longer is a need to manually install tailwind. Simply `dx serve` and you're good to go!
1616+1717+Automatic tailwind is supported by checking for a file called `tailwind.css` in your app's manifest directory (next to Cargo.toml). To customize the file, use the dioxus.toml:
1818+1919+```toml
2020+[application]
2121+tailwind_input = "my.css"
2222+tailwind_output = "assets/out.css" # also customize the location of the out file!
2323+```
2424+2525+### Tailwind Manual Install
2626+2727+To use tailwind plugins or manually customize tailwind, you can can install the Tailwind CLI and use it directly.
2828+2929+### Tailwind
3030+1. Install npm: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm
3131+2. Install the Tailwind CSS CLI: https://tailwindcss.com/docs/installation/tailwind-cli
3232+3. Run the following command in the root of the project to start the Tailwind CSS compiler:
3333+3434+```bash
3535+npx @tailwindcss/cli -i ./input.css -o ./assets/tailwind.css --watch
3636+```
3737+3838+### Serving Your App
3939+4040+Run the following command in the root of your project to start developing with the default platform:
4141+4242+```bash
4343+dx serve
4444+```
4545+4646+To run for a different platform, use the `--platform platform` flag. E.g.
4747+```bash
4848+dx serve --platform desktop
4949+```
5050+
···11+await-holding-invalid-types = [
22+ "generational_box::GenerationalRef",
33+ { path = "generational_box::GenerationalRef", reason = "Reads should not be held over an await point. This will cause any writes to fail while the await is pending since the read borrow is still active." },
44+ "generational_box::GenerationalRefMut",
55+ { path = "generational_box::GenerationalRefMut", reason = "Write should not be held over an await point. This will cause any reads or writes to fail while the await is pending since the write borrow is still active." },
66+ "dioxus_signals::WriteLock",
77+ { path = "dioxus_signals::WriteLock", reason = "Write should not be held over an await point. This will cause any reads or writes to fail while the await is pending since the write borrow is still active." },
88+]
+101
crates/tala/src/main.rs
···11+use dioxus::prelude::*;
22+33+#[derive(Debug, Clone, Routable, PartialEq)]
44+#[rustfmt::skip]
55+enum Route {
66+ #[layout(Navbar)]
77+ #[route("/")]
88+ Home {},
99+ #[route("/blog/:id")]
1010+ Blog { id: i32 },
1111+}
1212+1313+const FAVICON: Asset = asset!("/assets/favicon.ico");
1414+const MAIN_CSS: Asset = asset!("/assets/main.css");
1515+const HEADER_SVG: Asset = asset!("/assets/header.svg");
1616+const TAILWIND_CSS: Asset = asset!("/assets/tailwind.css");
1717+1818+fn main() {
1919+ dioxus::launch(App);
2020+}
2121+2222+#[component]
2323+fn App() -> Element {
2424+ rsx! {
2525+ document::Link { rel: "icon", href: FAVICON }
2626+ document::Link { rel: "stylesheet", href: MAIN_CSS } document::Link { rel: "stylesheet", href: TAILWIND_CSS }
2727+ Router::<Route> {}
2828+ }
2929+}
3030+3131+#[component]
3232+pub fn Hero() -> Element {
3333+ rsx! {
3434+ div {
3535+ id: "hero",
3636+ img { src: HEADER_SVG, id: "header" }
3737+ div { id: "links",
3838+ a { href: "https://dioxuslabs.com/learn/0.7/", "📚 Learn Dioxus" }
3939+ a { href: "https://dioxuslabs.com/awesome", "🚀 Awesome Dioxus" }
4040+ a { href: "https://github.com/dioxus-community/", "📡 Community Libraries" }
4141+ a { href: "https://github.com/DioxusLabs/sdk", "⚙️ Dioxus Development Kit" }
4242+ a { href: "https://marketplace.visualstudio.com/items?itemName=DioxusLabs.dioxus", "💫 VSCode Extension" }
4343+ a { href: "https://discord.gg/XgGxMSkvUM", "👋 Community Discord" }
4444+ }
4545+ }
4646+ }
4747+}
4848+4949+/// Home page
5050+#[component]
5151+fn Home() -> Element {
5252+ rsx! {
5353+ Hero {}
5454+5555+ }
5656+}
5757+5858+/// Blog page
5959+#[component]
6060+pub fn Blog(id: i32) -> Element {
6161+ rsx! {
6262+ div {
6363+ id: "blog",
6464+6565+ // Content
6666+ h1 { "This is blog #{id}!" }
6767+ p { "In blog #{id}, we show how the Dioxus router works and how URL parameters can be passed as props to our route components." }
6868+6969+ // Navigation links
7070+ Link {
7171+ to: Route::Blog { id: id - 1 },
7272+ "Previous"
7373+ }
7474+ span { " <---> " }
7575+ Link {
7676+ to: Route::Blog { id: id + 1 },
7777+ "Next"
7878+ }
7979+ }
8080+ }
8181+}
8282+8383+/// Shared navbar component.
8484+#[component]
8585+fn Navbar() -> Element {
8686+ rsx! {
8787+ div {
8888+ id: "navbar",
8989+ Link {
9090+ to: Route::Home {},
9191+ "Home"
9292+ }
9393+ Link {
9494+ to: Route::Blog { id: 1 },
9595+ "Blog"
9696+ }
9797+ }
9898+9999+ Outlet::<Route> {}
100100+ }
101101+}