Skip to content

Commit

Permalink
feat: Add widgets subsection
Browse files Browse the repository at this point in the history
  • Loading branch information
kdheepak committed Feb 19, 2024
1 parent 4cd46b2 commit 92704d0
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 17 deletions.
13 changes: 10 additions & 3 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,16 @@ export default defineConfig({
label: "crates_io_api Helper",
link: "/tutorials/crates-tui/crates_io_api_helper",
},
{ label: "Search", link: "/tutorials/crates-tui/search" },
{ label: "Results", link: "/tutorials/crates-tui/results" },
{ label: "Prompt", link: "/tutorials/crates-tui/prompt" },
{
label: "Widgets",
collapsed: true,
items: [
{ label: "Widgets", link: "/tutorials/crates-tui/widgets" },
{ label: "Search", link: "/tutorials/crates-tui/search" },
{ label: "Results", link: "/tutorials/crates-tui/results" },
{ label: "Prompt", link: "/tutorials/crates-tui/prompt" },
],
},
{ label: "Conclusion", link: "/tutorials/crates-tui/conclusion" },
],
},
Expand Down
2 changes: 1 addition & 1 deletion code/crates-tui-tutorial-app/src/widgets/search_prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl StatefulWidget for SearchPromptWidget {
type State = SearchPrompt;
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
let [input, meta] =
Layout::horizontal([Percentage(75), Fill(0)]).areas(area);
Layout::horizontal([Fill(0), Length(25)]).areas(area);

self.input_block().render(area, buf);

Expand Down
10 changes: 5 additions & 5 deletions code/crates-tui-tutorial-app/src/widgets/search_results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,15 @@ impl StatefulWidget for SearchResultsWidget {
}

fn row_from_crate(krate: &Crate) -> Row {
const ROW_HEIGHT: u16 = 3;
let vertical_padded = |line| Text::from(vec!["".into(), line, "".into()]);
const ROW_HEIGHT: u16 = 2;
let vertical_pad = |line| Text::from(vec!["".into(), line]);
let description = Line::from(krate.description.clone().unwrap_or_default());
let crate_name = Line::from(krate.name.clone());
let downloads = Line::from(krate.downloads.to_string()).right_aligned();
Row::new([
vertical_padded(crate_name),
vertical_padded(description),
vertical_padded(downloads),
vertical_pad(crate_name),
vertical_pad(description),
vertical_pad(downloads),
])
.height(ROW_HEIGHT)
}
8 changes: 3 additions & 5 deletions src/content/docs/tutorials/crates-tui/app_handle_action.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,9 @@ up from child to parent structs.
Any time the `rx` receiver receives an `Action` from _any_ `tx` transmitter, the application will
"handle the action" and the state of the application will update. This means you can, for example,
send a new variant `Action::Error(String)` from deep down in a nested child instance, which can
force the app to show an error message as a popup.

More relevant is that you can pass a clone of the `tx` into a tokio task, and have the tokio task
propagate information back to the `App` asynchronously. In this tutorial, we will use this to show a
loading message while the async request is being processed.
force the app to show an error message as a popup. You can also pass a clone of the `tx` into a
tokio task, and have the tokio task propagate information back to the `App` asynchronously. This is
particularly useful for error messages when a `.unwrap()` would normally fail in a tokio task.

<details>

Expand Down
9 changes: 6 additions & 3 deletions src/content/docs/tutorials/crates-tui/search.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ the `SearchPage` struct:
{{#include @code/crates-tui-tutorial-app/src/widgets/search_page.rs:search_page}}
```

This struct contains two nested children fields, `results` and `prompt` that contain the state of
the respective views.
This struct represents the `State` in the `StatefulWidget` pattern. This struct contains two nested
children fields, `results` and `prompt` that contain the state of the respective views.

As we saw in the previous section, we can create the search parameters struct like so:

Expand Down Expand Up @@ -39,7 +39,8 @@ This struct also contains methods for managing the prompt state using `tui_input

These methods are called from the `app` in the corresponding `Action`s.

For the search page widget, we render both the prompt and the results:
For the search page widget, we create struct with just one field, and we can implement the render
method on the `StatefulWidget` trait to render both the prompt and the results:

```rust
{{#include @code/crates-tui-tutorial-app/src/widgets/search_page.rs:search_page_widget}}
Expand All @@ -49,6 +50,8 @@ Here is the search page widget in its entirety:

<details>

<summary>Copy the following into <code>src/widgets/search_page.rs</code></summary>

```rust
{{#include @code/crates-tui-tutorial-app/src/widgets/search_page.rs}}
```
Expand Down
53 changes: 53 additions & 0 deletions src/content/docs/tutorials/crates-tui/widgets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
title: Widgets
---

In this section we will discuss the widgets implemented for this tutorial:

```rust
{{#include @code/crates-tui-tutorial-app/src/widgets.rs}}
```

We will be discussing a `SearchPage` widget that composes a `SearchResults` widget and a
`SearchPrompt` widget:

```plain
Name Description Downloads
█ ratatui A library tha 1021083

Check warning on line 19 in src/content/docs/tutorials/crates-tui/widgets.md

View workflow job for this annotation

GitHub Actions / typos

"tha" should be "than" or "that" or "the".
ratatui-textarea [deprecated] 1769
ratatui-macros Macros for Ra 487
tui-textarea tui-textarea 30526
ratatui-explorer ratatui-explo 29
ratatui-image An image widg 1820
▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
▏ ▕
▏ ratatui Sort By: Relevance ▕
▏ ▕
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
```

We will be using the `StatefulWidget` pattern. `StatefulWidget` is a Rust in Ratatui that is defined
like so:

```rust
pub trait StatefulWidget {
type State;
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
}
```

For this `StatefulWidget` pattern, we will always have at a minimum two `struct`s for every widget:

1. the state
2. the widget

What information you store in each of these structs is generally up to you and your application. We
will show a couple of different examples in this tutorial.

0 comments on commit 92704d0

Please sign in to comment.