Skip to content

Commit 8825c51

Browse files
committed
feat: add dioxus support && write docs
1 parent abb2f90 commit 8825c51

File tree

24 files changed

+4308
-120
lines changed

24 files changed

+4308
-120
lines changed

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ exclude = ["/assets", "/examples"]
1818
yew = { version = "0.21.0", default-features = false, optional = true }
1919
dioxus = { version = "0.6.3", optional = true }
2020
leptos = { version = "0.7.7", optional = true }
21-
web-sys = { version = "0.3.77", features = ["Window"]}
22-
gloo-timers = "0.3.0"
21+
web-sys = { version = "0.3.77", features = ["Window", "UrlSearchParams", "Url"]}
22+
gloo-timers = { version = "0.3.0", optional = true }
2323

2424
[features]
25-
yew = ["dep:yew"]
25+
yew = ["dep:yew", "gloo-timers"]
2626
dio = ["dioxus"]
2727
lep = ["leptos"]
2828

DIOXUS.md

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# 🧬 Table RS Dioxus Usage
2+
3+
Adding Table RS to your project is simple:
4+
5+
1. Make sure your project is set up with **Dioxus**. Refer to the [Dioxus Getting Started Guide](https://dioxuslabs.com/learn/0.6/getting_started) for setup instructions.
6+
7+
1. Add the **table-rs** library to your dependencies by including it in your `Cargo.toml` file:
8+
9+
```sh
10+
cargo add table-rs --features=dio
11+
```
12+
13+
1. Import the `Table` component into your Dioxus application.
14+
15+
## 🛠️ Usage
16+
17+
Incorporating Table RS into your Dioxus app involves just a few steps:
18+
19+
1. Import the `Table` component and types:
20+
21+
```rust
22+
use dioxus::prelude::*;
23+
use table_rs::dioxus::table::Table;
24+
use table_rs::dioxus::types::Column;
25+
use maplit::hashmap;
26+
```
27+
28+
1. Use the `Table` component in your Dioxus app:
29+
30+
```rust
31+
use dioxus::prelude::*;
32+
use table_rs::dioxus::table::Table;
33+
use table_rs::dioxus::types::Column;
34+
use maplit::hashmap;
35+
36+
37+
fn App() -> Element {
38+
let data = vec![
39+
hashmap! { "name" => "Ferris".to_string(), "email" => "ferris@opensass.org".to_string() },
40+
hashmap! { "name" => "Ferros".to_string(), "email" => "ferros@opensass.org".to_string() },
41+
hashmap! { "name" => "Crab".to_string(), "email" => "crab@opensass.org".to_string() },
42+
];
43+
44+
let columns = vec![
45+
Column {
46+
id: "name",
47+
header: "Name",
48+
sortable: true,
49+
..Default::default()
50+
},
51+
Column {
52+
id: "email",
53+
header: "Email",
54+
sortable: false,
55+
..Default::default()
56+
},
57+
];
58+
59+
rsx! {
60+
Table {
61+
data: data,
62+
columns: columns,
63+
}
64+
}
65+
}
66+
```
67+
68+
## 🔧 Props
69+
70+
### `Table` Component Props
71+
72+
| Prop | Type | Description | Default |
73+
| ----------- | ------------------------------------- | --------------------------------- | ------- |
74+
| `data` | `Vec<HashMap<&'static str, String>>` | The row data to render. | `[]` |
75+
| `columns` | `Vec<Column>` | Column definitions. | `[]` |
76+
| `page_size` | `usize` | Number of rows per page. | `10` |
77+
| `loading` | `bool` | Show loading state if true. | `false` |
78+
| `paginate` | `bool` | Enable pagination. | `false` |
79+
| `search` | `bool` | Enable global search input. | `false` |
80+
| `classes` | `TableClasses` | CSS class overrides. | Default |
81+
| `styles` | `HashMap<&'static str, &'static str>` | Inline style overrides. | `{}` |
82+
| `texts` | `TableTexts` | Text customization for UI labels. | Default |
83+
84+
### `Column` Props
85+
86+
| Prop | Type | Description | Default |
87+
| ---------- | ---------------------- | ----------------------------------------- | --------------------------------------------------------- |
88+
| `id` | `&'static str` | Column key (used to fetch from row data). | `""` |
89+
| `header` | `&'static str` | Display name in the table header. | `""` |
90+
| `sortable` | `bool` | Allow sorting on this column. | `false` |
91+
| `style` | `Option<&'static str>` | Inline CSS for the header. | Some("padding: 8px; font-weight: 600; text-align: left;") |
92+
| `class` | `Option<&'static str>` | Optional class name for this column. | Some("table-header-cell") |
93+
94+
### `TableClasses`
95+
96+
| Prop | Type | Description | Default |
97+
| ------------------- | -------------- | ------------------------------------ | ----------------------- |
98+
| `container` | `&'static str` | Outer container class. | `"table-container"` |
99+
| `table` | `&'static str` | Main table class. | `"table"` |
100+
| `thead` | `&'static str` | Table head (`<thead>`) class. | `"thead"` |
101+
| `tbody` | `&'static str` | Table body (`<tbody>`) class. | `"tbody"` |
102+
| `row` | `&'static str` | Row (`<tr>`) class. | `"tr"` |
103+
| `header_cell` | `&'static str` | Header cell (`<th>`) class. | `"th"` |
104+
| `body_cell` | `&'static str` | Body cell (`<td>`) class. | `"td"` |
105+
| `loading_row` | `&'static str` | Row shown when loading. | `"loading-row"` |
106+
| `empty_row` | `&'static str` | Row shown when no data is available. | `"empty-row"` |
107+
| `search_input` | `&'static str` | Search input field class. | `"search-input"` |
108+
| `pagination` | `&'static str` | Pagination controls wrapper. | `"pagination-controls"` |
109+
| `pagination_button` | `&'static str` | Pagination buttons. | `"pagination-button"` |
110+
111+
### `TableTexts`
112+
113+
| Prop | Type | Description | Default |
114+
| -------------------- | -------------- | --------------------------------- | ----------------------------- |
115+
| `loading` | `&'static str` | Text shown when loading. | `"Loading..."` |
116+
| `empty` | `&'static str` | Text when no data is present. | `"No results found"` |
117+
| `search_placeholder` | `&'static str` | Placeholder for search input. | `"Search..."` |
118+
| `previous_button` | `&'static str` | Label for previous page button. | `"Previous"` |
119+
| `next_button` | `&'static str` | Label for next page button. | `"Next"` |
120+
| `page_indicator` | `&'static str` | Format string for page indicator. | `"Page {current} of {total}"` |
121+
122+
### 🧱 Style/Layout Structure
123+
124+
```sh
125+
+-------------------------------------------------------------+
126+
| [container] | <-- class: "table-container"
127+
| |
128+
| +-----------------------------------------------------+ |
129+
| | [search_input] | | <-- class: "search-input"
130+
| | (optional search <input> element) | |
131+
| +-----------------------------------------------------+ |
132+
| |
133+
| +-----------------------------------------------------+ |
134+
| | [table] | | <-- class: "table"
135+
| | +--------------------[thead]--------------------+ | | <-- class: "thead"
136+
| | | Column Headers (e.g., Name, Email) | | |
137+
| | +-----------------------------------------------+ | |
138+
| | +--------------------[tbody]--------------------+ | | <-- class: "tbody"
139+
| | | Data rows (from `data` prop, each row = <tr>)| | |
140+
| | +-----------------------------------------------+ | |
141+
| +-----------------------------------------------------+ |
142+
| |
143+
| +-----------------------------------------------------+ |
144+
| | [pagination] | | <-- class: "pagination-controls"
145+
| | Page selector / next-prev buttons (if enabled) | |
146+
| +-----------------------------------------------------+ |
147+
+-------------------------------------------------------------+
148+
```
149+
150+
## 💡 Notes
151+
152+
- The `data` must match the `id` values defined in each `Column`.
153+
- The `search` prop enables input-based filtering across all columns.
154+
- Pagination is controlled using the `page_size` and `paginate` props.
155+
- Sorting is column-specific via `sortable = true` and `on_sort_column`.
156+
- All style classes can be customized via `TableClasses`.
157+
- All texts are configurable via `TableTexts`.
158+
- The component handles loading and empty states out-of-the-box.
159+
- You can inject additional per-column styling via `Column.style` and `Column.class`.

README.md

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
| Framework | Live Demo |
2222
| --------- | ------------------------------------------------------------------------------------------------------------------------ |
2323
| Yew | [![Netlify Status](https://api.netlify.com/api/v1/badges/4e1494d6-c19a-4a4c-b2d3-47d964214a71/deploy-status)](https://table-rs.netlify.app) |
24-
| Dioxus | TODO |
24+
| Dioxus | [![Netlify Status](https://api.netlify.com/api/v1/badges/4e1494d6-c19a-4a4c-b2d3-47d964214a71/deploy-status)](https://table-dio.netlify.app) |
2525
| Leptos | TODO |
2626

2727
## 📜 Intro
@@ -44,7 +44,7 @@ The following are some of the reasons why **Table RS** should be your go-to tabl
4444
<!-- absolute url for docs.rs cause YEW.md is not included in crate -->
4545
Refer to [our guide](https://github.com/opensass/table-rs/blob/main/YEW.md) to integrate this component into your Yew app.
4646

47-
## 🧬 Dioxus Usage (TODO)
47+
## 🧬 Dioxus Usage
4848

4949
<!-- absolute url for docs.rs cause DIOXUS.md is not included in crate -->
5050
Refer to [our guide](https://github.com/opensass/table-rs/blob/main/DIOXUS.md) to integrate this component into your Dioxus app.
@@ -54,35 +54,6 @@ Refer to [our guide](https://github.com/opensass/table-rs/blob/main/DIOXUS.md) t
5454
<!-- absolute url for docs.rs cause LEPTOS.md is not included in crate -->
5555
Refer to [our guide](https://github.com/opensass/table-rs/blob/main/LEPTOS.md) to integrate this component into your Leptos app.
5656

57-
## 📊 Benchmark: TanStack Table vs Table RS
58-
59-
| Metric | TanStack Table (React) | Table RS (Yew + WASM) |
60-
|--------------------------------|-----------------------------|----------------------------|
61-
| **Page Load Time (1M rows)** | ~10 seconds | ~2 seconds |
62-
| **Memory Heap Usage** | >3 GB (heap overflow) | ~1.1 GB (stable) |
63-
| **Initial Rendering** | Heavy blocking, slow DOM paint | Efficient, lightweight rendering |
64-
| **Browser Responsiveness** | Delayed interactivity | Smooth after hydration |
65-
| **Sorting Performance** | 2-4s for large columns | Sub-1s due to WASM speed |
66-
| **Search Performance** | Acceptable, but slower | Instantaneous, even at scale |
67-
| **Lighthouse Performance Score** | 49/100 | 60/100 |
68-
| **Scalability** | Limited due to memory and VDOM | Near-native scalability |
69-
70-
### 🟨 TanStack Table (React)
71-
- Uses Virtual DOM and JS heap to manage massive data.
72-
- Runtime bottlenecks emerge with >100k rows.
73-
- Memory allocation during sorting and filtering can spike to **3GB+**, often leading to **heap overflow** during intensive usage.
74-
- Lighthouse audit shows poor TTI and CPU blocking.
75-
76-
### 🟩 Table RS (Yew + WASM)
77-
- WASM-compiled logic is highly memory-efficient and deterministic.
78-
- DOM rendering is direct, bypassing React's reconciliation.
79-
- ~1.1 GB of memory heap used even with **1 million rows**.
80-
- Built-in support for search/sort with stable paging.
81-
- No hydration issues (client-only generation).
82-
- Lighthouse performance significantly better, especially in CPU/Memory metrics.
83-
84-
For large-data UI benchmarks like tables with millions of rows, **`table-rs` in Yew/WASM is a superior choice** compared to React + TanStack.
85-
8657
## 🤝 Contributions
8758

8859
Contributions are welcome! Whether it's bug fixes, feature requests, or examples, we would love your help to make **Table RS** even better.

0 commit comments

Comments
 (0)