rooibos 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSES/BSD-2-Clause.txt +9 -0
- data/REUSE.toml +5 -0
- data/exe/.gitkeep +0 -0
- data/lib/rooibos/cli/commands/new.rb +24 -0
- data/lib/rooibos/command/batch.rb +10 -0
- data/lib/rooibos/command/bubble.rb +34 -0
- data/lib/rooibos/command/custom.rb +3 -2
- data/lib/rooibos/command/deliver.rb +50 -0
- data/lib/rooibos/command/http.rb +1 -1
- data/lib/rooibos/command/lifecycle.rb +3 -1
- data/lib/rooibos/command/outlet.rb +19 -9
- data/lib/rooibos/command.rb +107 -3
- data/lib/rooibos/configuration.rb +29 -0
- data/lib/rooibos/message/bubbled.rb +29 -0
- data/lib/rooibos/message.rb +24 -6
- data/lib/rooibos/router/action.rb +36 -0
- data/lib/rooibos/router/flow/dispatch.rb +39 -0
- data/lib/rooibos/router/flow/inward.rb +41 -0
- data/lib/rooibos/router/flow/outward.rb +44 -0
- data/lib/rooibos/router/guard.rb +56 -0
- data/lib/rooibos/router/predicate.rb +65 -0
- data/lib/rooibos/router/registry/actions.rb +41 -0
- data/lib/rooibos/router/registry/forwards.rb +58 -0
- data/lib/rooibos/router/registry/observes.rb +57 -0
- data/lib/rooibos/router/registry/otherwises.rb +29 -0
- data/lib/rooibos/router/registry/receives.rb +57 -0
- data/lib/rooibos/router/registry/routes.rb +59 -0
- data/lib/rooibos/router/registry.rb +26 -0
- data/lib/rooibos/router/route.rb +42 -0
- data/lib/rooibos/router/router_update.rb +53 -0
- data/lib/rooibos/router/rule/forward.rb +39 -0
- data/lib/rooibos/router/rule/observe.rb +22 -0
- data/lib/rooibos/router/rule/otherwise.rb +26 -0
- data/lib/rooibos/router/rule/receive.rb +22 -0
- data/lib/rooibos/router/rule.rb +40 -0
- data/lib/rooibos/router.rb +424 -438
- data/lib/rooibos/runtime.rb +37 -52
- data/lib/rooibos/test_helper.rb +22 -0
- data/lib/rooibos/transition.rb +92 -0
- data/lib/rooibos/version.rb +1 -1
- data/lib/rooibos.rb +2 -57
- data/sig/rooibos/cli.rbs +1 -0
- data/sig/rooibos/command.rbs +44 -0
- data/sig/rooibos/configuration.rbs +20 -0
- data/sig/rooibos/message.rbs +12 -0
- data/sig/rooibos/router/action.rbs +33 -0
- data/sig/rooibos/router/actions.rbs +27 -0
- data/sig/rooibos/router/flow/dispatch.rbs +29 -0
- data/sig/rooibos/router/flow/inward.rbs +37 -0
- data/sig/rooibos/router/flow/outward.rbs +36 -0
- data/sig/rooibos/router/forward.rbs +35 -0
- data/sig/rooibos/router/forwards.rbs +34 -0
- data/sig/rooibos/router/guard.rbs +21 -0
- data/sig/rooibos/router/observe.rbs +20 -0
- data/sig/rooibos/router/observes.rbs +38 -0
- data/sig/rooibos/router/otherwise.rbs +22 -0
- data/sig/rooibos/router/otherwises.rbs +20 -0
- data/sig/rooibos/router/predicate.rbs +51 -0
- data/sig/rooibos/router/receive.rbs +20 -0
- data/sig/rooibos/router/receives.rbs +38 -0
- data/sig/rooibos/router/registry.rbs +24 -0
- data/sig/rooibos/router/route.rbs +46 -0
- data/sig/rooibos/router/router_update.rbs +33 -0
- data/sig/rooibos/router/routes.rbs +41 -0
- data/sig/rooibos/router/rule.rbs +36 -0
- data/sig/rooibos/router.rbs +216 -161
- data/sig/rooibos/runtime.rbs +0 -1
- data/sig/rooibos/test_helper.rbs +6 -0
- data/sig/rooibos/transition.rbs +33 -0
- data/sig/rooibos.rbs +0 -10
- metadata +144 -198
- data/.builds/ruby-3.2.yml +0 -55
- data/.builds/ruby-3.3.yml +0 -55
- data/.builds/ruby-3.4.yml +0 -55
- data/.builds/ruby-4.0.0.yml +0 -55
- data/.pre-commit-config.yaml +0 -16
- data/.rubocop.yml +0 -8
- data/AGENTS.md +0 -108
- data/CHANGELOG.md +0 -308
- data/README.md +0 -183
- data/README.rdoc +0 -374
- data/Rakefile +0 -16
- data/Steepfile +0 -13
- data/doc/best_practices/forms_and_validation.md +0 -20
- data/doc/best_practices/http_workflows.md +0 -20
- data/doc/best_practices/index.md +0 -26
- data/doc/best_practices/lists_and_tables.md +0 -20
- data/doc/best_practices/modal_dialogs.md +0 -20
- data/doc/best_practices/no_stateful_widgets.md +0 -184
- data/doc/best_practices/orchestration.md +0 -20
- data/doc/best_practices/streaming_data.md +0 -20
- data/doc/contributors/design/commands_and_outlets.md +0 -214
- data/doc/contributors/design/mvu_tea_implementations_research.md +0 -373
- data/doc/contributors/documentation_plan.md +0 -616
- data/doc/contributors/documentation_stub_audit.md +0 -112
- data/doc/contributors/documentation_style.md +0 -275
- data/doc/contributors/e2e_pty.md +0 -168
- data/doc/contributors/maybe_stateful_router.md +0 -56
- data/doc/contributors/specs/earliest_tutorial_steps_per_story.md +0 -70
- data/doc/contributors/specs/file_browser.md +0 -789
- data/doc/contributors/specs/file_browser_stories.md +0 -784
- data/doc/contributors/specs/tutorials_to_stories.rb +0 -167
- data/doc/contributors/todo/scrollbar.md +0 -118
- data/doc/contributors/tutorial_old/01_project_setup.md +0 -20
- data/doc/contributors/tutorial_old/02_hello_world.md +0 -24
- data/doc/contributors/tutorial_old/03_adding_state.md +0 -26
- data/doc/contributors/tutorial_old/06_organizing_your_code.md +0 -20
- data/doc/contributors/tutorial_old/07_your_first_command.md +0 -21
- data/doc/contributors/tutorial_old/08_the_preview_pane.md +0 -20
- data/doc/contributors/tutorial_old/09_loading_states.md +0 -20
- data/doc/contributors/tutorial_old/10_testing_your_app.md +0 -20
- data/doc/contributors/tutorial_old/11_polish_and_refine.md +0 -20
- data/doc/contributors/tutorial_old/12_going_further.md +0 -20
- data/doc/contributors/tutorial_old/index.md +0 -20
- data/doc/custom.css +0 -22
- data/doc/essentials/commands.md +0 -20
- data/doc/essentials/index.md +0 -31
- data/doc/essentials/messages.md +0 -21
- data/doc/essentials/models.md +0 -21
- data/doc/essentials/shortcuts.md +0 -19
- data/doc/essentials/the_elm_architecture.md +0 -24
- data/doc/essentials/the_runtime.md +0 -21
- data/doc/essentials/update_functions.md +0 -20
- data/doc/essentials/views.md +0 -22
- data/doc/getting_started/for_go_developers.md +0 -16
- data/doc/getting_started/for_python_developers.md +0 -16
- data/doc/getting_started/for_rails_developers.md +0 -17
- data/doc/getting_started/for_ratatui_ruby_developers.md +0 -17
- data/doc/getting_started/for_react_developers.md +0 -17
- data/doc/getting_started/index.md +0 -52
- data/doc/getting_started/install.md +0 -20
- data/doc/getting_started/quickstart.md +0 -20
- data/doc/getting_started/ruby_primer.md +0 -19
- data/doc/getting_started/why_rooibos.md +0 -20
- data/doc/images/verify_readme_usage.png +0 -0
- data/doc/images/widget_cmd_exec.png +0 -0
- data/doc/index.md +0 -93
- data/doc/scaling_up/async_patterns.md +0 -20
- data/doc/scaling_up/command_composition.md +0 -20
- data/doc/scaling_up/custom_commands.md +0 -21
- data/doc/scaling_up/fractal_architecture.md +0 -20
- data/doc/scaling_up/index.md +0 -30
- data/doc/scaling_up/message_routing.md +0 -20
- data/doc/scaling_up/ractor_safety.md +0 -20
- data/doc/scaling_up/testing.md +0 -21
- data/doc/troubleshooting/common_errors.md +0 -20
- data/doc/troubleshooting/debugging.md +0 -21
- data/doc/troubleshooting/index.md +0 -23
- data/doc/troubleshooting/performance.md +0 -20
- data/doc/tutorial/01_project_setup.md +0 -44
- data/doc/tutorial/02_hello_world.md +0 -45
- data/doc/tutorial/03_static_file_list.md +0 -44
- data/doc/tutorial/04_arrow_navigation.md +0 -47
- data/doc/tutorial/05_real_files.md +0 -45
- data/doc/tutorial/06_safe_refactoring.md +0 -21
- data/doc/tutorial/07_red_first_tdd.md +0 -26
- data/doc/tutorial/08_file_metadata.md +0 -42
- data/doc/tutorial/09_text_preview.md +0 -44
- data/doc/tutorial/10_directory_tree.md +0 -42
- data/doc/tutorial/11_pane_focus.md +0 -40
- data/doc/tutorial/12_sorting.md +0 -41
- data/doc/tutorial/13_filtering.md +0 -43
- data/doc/tutorial/14_toggle_hidden.md +0 -41
- data/doc/tutorial/15_text_input_widget.md +0 -43
- data/doc/tutorial/16_rename_files.md +0 -42
- data/doc/tutorial/17_confirmation_dialogs.md +0 -43
- data/doc/tutorial/18_progress_indicators.md +0 -43
- data/doc/tutorial/19_atomic_operations.md +0 -42
- data/doc/tutorial/20_external_editor.md +0 -42
- data/doc/tutorial/21_modal_overlays.md +0 -41
- data/doc/tutorial/22_error_handling.md +0 -43
- data/doc/tutorial/23_terminal_capabilities.md +0 -53
- data/doc/tutorial/24_mouse_events.md +0 -43
- data/doc/tutorial/25_resize_events.md +0 -43
- data/doc/tutorial/26_loading_states.md +0 -42
- data/doc/tutorial/27_performance.md +0 -43
- data/doc/tutorial/28_color_schemes.md +0 -47
- data/doc/tutorial/29_configuration.md +0 -124
- data/doc/tutorial/30_going_further.md +0 -17
- data/doc/tutorial/index.md +0 -17
- data/examples/app_fractal_dashboard/README.md +0 -60
- data/examples/app_fractal_dashboard/app.rb +0 -63
- data/examples/app_fractal_dashboard/dashboard/base.rb +0 -73
- data/examples/app_fractal_dashboard/dashboard/update_helpers.rb +0 -86
- data/examples/app_fractal_dashboard/dashboard/update_manual.rb +0 -87
- data/examples/app_fractal_dashboard/dashboard/update_router.rb +0 -43
- data/examples/app_fractal_dashboard/fragments/custom_shell_input.rb +0 -81
- data/examples/app_fractal_dashboard/fragments/custom_shell_modal.rb +0 -82
- data/examples/app_fractal_dashboard/fragments/custom_shell_output.rb +0 -90
- data/examples/app_fractal_dashboard/fragments/disk_usage.rb +0 -47
- data/examples/app_fractal_dashboard/fragments/network_panel.rb +0 -45
- data/examples/app_fractal_dashboard/fragments/ping.rb +0 -47
- data/examples/app_fractal_dashboard/fragments/stats_panel.rb +0 -45
- data/examples/app_fractal_dashboard/fragments/system_info.rb +0 -47
- data/examples/app_fractal_dashboard/fragments/uptime.rb +0 -47
- data/examples/tutorial/01/app.rb +0 -50
- data/examples/tutorial/02/app.rb +0 -64
- data/examples/tutorial/03/app.rb +0 -91
- data/examples/tutorial/06_safe_refactoring/app.rb +0 -124
- data/examples/verify_readme_usage/README.md +0 -54
- data/examples/verify_readme_usage/app.rb +0 -47
- data/examples/verify_website_first_app/app.rb +0 -85
- data/examples/verify_website_hello_mvu/app.rb +0 -31
- data/examples/widget_command_system/README.md +0 -70
- data/examples/widget_command_system/app.rb +0 -134
- data/generate_tutorial_stubs.rb +0 -126
- data/mise.toml +0 -8
- data/rbs_collection.lock.yaml +0 -108
- data/rbs_collection.yaml +0 -15
- data/tasks/example_viewer.html.erb +0 -172
- data/tasks/install.rake +0 -29
- data/tasks/resources/build.yml.erb +0 -55
- data/tasks/resources/index.html.erb +0 -44
- data/tasks/resources/rubies.yml +0 -7
- data/tasks/steep.rake +0 -11
- /data/{vendor/goodcop/base.yml → lib/rooibos/rubocop.yml} +0 -0
data/README.md
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
# rooibos
|
|
6
|
-
|
|
7
|
-
[](https://builds.sr.ht/~kerrick/rooibos?) [%22&replace=%241&label=License&color=a2c93e)](https://spdx.org/licenses/LGPL-3.0-or-later.html) [](https://rubygems.org/gems/rooibos) [](https://rubygems.org/gems/rooibos) [](https://lists.sr.ht/~kerrick/ratatui_ruby-discuss) [](https://lists.sr.ht/~kerrick/ratatui_ruby-devel) [](https://lists.sr.ht/~kerrick/ratatui_ruby-announce)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
## Introduction
|
|
18
|
-
|
|
19
|
-
**rooibos** is a gem in the [RatatuiRuby ecosystem](https://sr.ht/~kerrick/ratatui_ruby/).
|
|
20
|
-
**ratatui_ruby** is a community wrapper that is not affiliated with [the Ratatui team](https://github.com/orgs/ratatui/people).
|
|
21
|
-
|
|
22
|
-
> [!WARNING]
|
|
23
|
-
> **rooibos** is currently in **BETA**. The API may change with minor versions.
|
|
24
|
-
|
|
25
|
-
**[Why RatatuiRuby?](https://man.sr.ht/~kerrick/ratatui_ruby/why.md)** — Native Rust performance, zero runtime overhead, and Ruby's expressiveness. [See how we compare](https://man.sr.ht/~kerrick/ratatui_ruby/why.md) to CharmRuby, raw Rust, and Go.
|
|
26
|
-
|
|
27
|
-
Please join the **announce** mailing list at https://lists.sr.ht/~kerrick/ratatui_ruby-announce to stay up-to-date on new releases and announcements. See the [`trunk` branch](https://git.sr.ht/~kerrick/rooibos/tree/trunk) for pre-release updates.
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## Quick Links
|
|
32
|
-
|
|
33
|
-
### The Ecosystem
|
|
34
|
-
|
|
35
|
-
**RatatuiRuby:** [Core engine](https://git.sr.ht/~kerrick/ratatui_ruby) • **Tea:** [MVU architecture](https://git.sr.ht/~kerrick/rooibos) • **Kit:** [Component architecture](https://git.sr.ht/~kerrick/ratatui_ruby-kit) (Planned) • **DSL:** [Glimmer syntax](https://sr.ht/~kerrick/ratatui_ruby/#chapter-4-the-syntax) (Planned) • **Framework:** [Omakase framework](https://git.sr.ht/~kerrick/ratatui_ruby-framework) (Planned) • **UI:** [Polished widgets](https://git.sr.ht/~kerrick/ratatui_ruby-ui) (Planned) • **UI Pro:** [More polished widgets](https://sr.ht/~kerrick/ratatui_ruby#chapter-6-licensing) (Planned)
|
|
36
|
-
|
|
37
|
-
### For App Developers
|
|
38
|
-
|
|
39
|
-
**Get Started:** [Quickstart](https://git.sr.ht/~kerrick/ratatui_ruby/tree/stable/item/doc/getting_started/quickstart.md) • [Examples](https://git.sr.ht/~kerrick/ratatui_ruby/tree/stable/item/examples) ⸺ **Stay Informed:** [Announce List](https://lists.sr.ht/~kerrick/ratatui_ruby-announce) • [FAQ](https://man.sr.ht/~kerrick/ratatui_ruby/troubleshooting.md) ⸺ **Reach Out:** [Discuss List](https://lists.sr.ht/~kerrick/ratatui_ruby-discuss) • [Bug Tracker](https://todo.sr.ht/~kerrick/ratatui_ruby)
|
|
40
|
-
|
|
41
|
-
### For Contributors
|
|
42
|
-
|
|
43
|
-
**Get Started:** [Contributing Guide](https://man.sr.ht/~kerrick/ratatui_ruby/contributing.md) • [Code of Conduct](https://man.sr.ht/~kerrick/ratatui_ruby/code_of_conduct.md) ⸺ **Stay Informed:** [Announce List](https://lists.sr.ht/~kerrick/ratatui_ruby-announce) • [Project History](https://man.sr.ht/~kerrick/ratatui_ruby/history/index.md) ⸺ **Reach Out:** [Development List](https://lists.sr.ht/~kerrick/ratatui_ruby-devel) • [Bug Tracker](https://todo.sr.ht/~kerrick/ratatui_ruby)
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Compatibility
|
|
48
|
-
|
|
49
|
-
**rooibos** is designed to run on [everything Ruby does](https://www.ruby-lang.org/en/documentation/installation/), including:
|
|
50
|
-
|
|
51
|
-
- GNU/Linux, macOS, Windows, OpenBSD, and FreeBSD; and
|
|
52
|
-
- x86_64 (AMD, Intel) and ARM (Apple Silicon, Raspberry Pi).
|
|
53
|
-
|
|
54
|
-
We support the latest minor version of every
|
|
55
|
-
[non-eol Ruby version](https://www.ruby-lang.org/en/downloads/branches/),
|
|
56
|
-
including Ruby 4.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
## Installation
|
|
60
|
-
|
|
61
|
-
Add this line to your application's Gemfile:
|
|
62
|
-
|
|
63
|
-
<!-- SPDX-SnippetBegin -->
|
|
64
|
-
<!--
|
|
65
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
66
|
-
SPDX-License-Identifier: MIT-0
|
|
67
|
-
-->
|
|
68
|
-
```ruby
|
|
69
|
-
gem "rooibos"
|
|
70
|
-
```
|
|
71
|
-
<!-- SPDX-SnippetEnd -->
|
|
72
|
-
|
|
73
|
-
And then execute:
|
|
74
|
-
|
|
75
|
-
<!-- SPDX-SnippetBegin -->
|
|
76
|
-
<!--
|
|
77
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
78
|
-
SPDX-License-Identifier: MIT-0
|
|
79
|
-
-->
|
|
80
|
-
```bash
|
|
81
|
-
bundle install
|
|
82
|
-
```
|
|
83
|
-
<!-- SPDX-SnippetEnd -->
|
|
84
|
-
|
|
85
|
-
Or install it yourself with:
|
|
86
|
-
|
|
87
|
-
<!-- SPDX-SnippetBegin -->
|
|
88
|
-
<!--
|
|
89
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
90
|
-
SPDX-License-Identifier: MIT-0
|
|
91
|
-
-->
|
|
92
|
-
```bash
|
|
93
|
-
gem install rooibos
|
|
94
|
-
```
|
|
95
|
-
<!-- SPDX-SnippetEnd -->
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
## Usage
|
|
99
|
-
|
|
100
|
-
**rooibos** uses the Model-View-Update (MVU) pattern. You provide an immutable model, a view function, and an update function.
|
|
101
|
-
|
|
102
|
-
<!-- SPDX-SnippetBegin -->
|
|
103
|
-
<!--
|
|
104
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
105
|
-
SPDX-License-Identifier: MIT-0
|
|
106
|
-
-->
|
|
107
|
-
<!-- SYNC:START:examples/verify_readme_usage/app.rb:mvu -->
|
|
108
|
-
```ruby
|
|
109
|
-
Model = Data.define(:text)
|
|
110
|
-
|
|
111
|
-
Init = -> do
|
|
112
|
-
Model.new(text: "Hello, Ratatui! Press 'q' to quit.")
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
View = -> (model, tui) do
|
|
116
|
-
tui.paragraph(
|
|
117
|
-
text: model.text,
|
|
118
|
-
alignment: :center,
|
|
119
|
-
block: tui.block(
|
|
120
|
-
title: "My Ruby TUI App",
|
|
121
|
-
borders: [:all],
|
|
122
|
-
border_style: { fg: "cyan" }
|
|
123
|
-
)
|
|
124
|
-
)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
Update = -> (msg, model) do
|
|
128
|
-
if msg.q? || msg.ctrl_c?
|
|
129
|
-
Rooibos::Command.exit
|
|
130
|
-
else
|
|
131
|
-
model
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def run
|
|
136
|
-
Rooibos.run(VerifyReadmeUsage)
|
|
137
|
-
end
|
|
138
|
-
```
|
|
139
|
-
<!-- SYNC:END -->
|
|
140
|
-
<!-- SPDX-SnippetEnd -->
|
|
141
|
-
|
|
142
|
-

|
|
143
|
-
|
|
144
|
-
For a full tutorial, see [the Quickstart](./doc/getting_started/quickstart.md). For an explanation of the application architecture, see [Application Architecture](./doc/concepts/application_architecture.md).
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
## Features
|
|
148
|
-
|
|
149
|
-
_Because this gem is in alpha, it lacks documentation. Please check the source files._
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
## Documentation
|
|
153
|
-
|
|
154
|
-
| Resource | Description |
|
|
155
|
-
|----------|-------------|
|
|
156
|
-
| [Quickstart](./doc/getting_started/quickstart.md) | Get running in 5 minutes |
|
|
157
|
-
| [Application Architecture](./doc/concepts/application_architecture.md) | Patterns for scaling your app |
|
|
158
|
-
| [Guides](./doc/index.md) | Tutorials, examples, and more |
|
|
159
|
-
| API Reference | To generate full RDoc documentation, run `bundle exec rake rdoc` |
|
|
160
|
-
| [Wiki](https://man.sr.ht/~kerrick/ratatui_ruby) | Learn more about the RatatuiRuby ecosystem |
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
## Contributing
|
|
164
|
-
|
|
165
|
-
Bug reports and pull requests are welcome on [sourcehut](https://sourcehut.org) at https://sr.ht/~kerrick/ratatui_ruby/. This project is intended to be a safe, productive collaboration, and contributors are expected to adhere to the [Code of Conduct](https://man.sr.ht/~kerrick/ratatui_ruby/code_of_conduct.md).
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
Want to help develop **rooibos**? Check out the [contribution guide on the wiki](https://man.sr.ht/~kerrick/ratatui_ruby/contributing.md).
|
|
169
|
-
|
|
170
|
-
**Note**: Active development happens on the `trunk` branch. Use `trunk` if you are a contributor or want the latest cutting-edge features. `stable` is for stable releases only.
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
## Copyright & License
|
|
174
|
-
|
|
175
|
-
**rooibos** is copyright 2026, Kerrick Long.
|
|
176
|
-
|
|
177
|
-
The library is [LGPL-3.0-or-later](./LICENSES/LGPL-3.0-or-later.txt): you can use it in proprietary applications, but you must share changes you make to **rooibos** itself. Documentation snippets and widget examples are [MIT-0](./LICENSES/MIT-0.txt): copy and use them without attribution.
|
|
178
|
-
|
|
179
|
-
Documentation is [CC-BY-SA-4.0](./LICENSES/CC-BY-SA-4.0.txt). Build tooling and full app examples are [LGPL-3.0-or-later](./LICENSES/LGPL-3.0-or-later.txt). See each file's SPDX comment for specifics.
|
|
180
|
-
|
|
181
|
-
Some parts of this program are copied from other sources under appropriate reuse licenses, and the copyright belongs to their respective owners. See the [REUSE Specification – Version 3.3](https://reuse.software/spec-3.3/) for details.
|
|
182
|
-
|
|
183
|
-
This program was created with significant assistance from multiple LLMs. The process was human-controlled through creative prompts, with human contributions to each commit. See commit footers for model attribution. [declare-ai.org](https://declare-ai.org/1.0.0/creative.html)
|
data/README.rdoc
DELETED
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
== Confidently Build Terminal Apps
|
|
2
|
-
|
|
3
|
-
Rooibos[https://rooibos.run] helps you build interactive terminal applications.
|
|
4
|
-
Keep your code understandable and testable as it scales. Rooibos handles
|
|
5
|
-
keyboard, mouse, and async work so you can focus on behavior and user experience.
|
|
6
|
-
|
|
7
|
-
gem install rooibos
|
|
8
|
-
|
|
9
|
-
<i>Currently in beta. APIs may change before 1.0.</i>
|
|
10
|
-
|
|
11
|
-
=== Get Started in Seconds
|
|
12
|
-
|
|
13
|
-
rooibos new my_app
|
|
14
|
-
cd my_app
|
|
15
|
-
rooibos run
|
|
16
|
-
|
|
17
|
-
That's it. You have a working app with keyboard navigation, mouse support,
|
|
18
|
-
and clickable buttons. Open <tt>lib/my_app.rb</tt> to make it your own.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
=== The Pattern
|
|
24
|
-
|
|
25
|
-
\Rooibos uses Model-View-Update, the architecture behind
|
|
26
|
-
Elm[https://guide.elm-lang.org/architecture/],
|
|
27
|
-
Redux[https://redux.js.org/], and {Bubble
|
|
28
|
-
Tea}[https://github.com/charmbracelet/bubbletea].
|
|
29
|
-
State lives in one place. Updates flow in one direction. The runtime handles
|
|
30
|
-
rendering and runs background work for you.
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
=== Hello, MVU
|
|
35
|
-
|
|
36
|
-
The simplest \Rooibos app. Press any key to increment the counter. Press
|
|
37
|
-
<tt>Ctrl</tt>+<tt>C</tt> to quit.
|
|
38
|
-
|
|
39
|
-
require "rooibos"
|
|
40
|
-
|
|
41
|
-
module Counter
|
|
42
|
-
# Init: How do you create the initial model?
|
|
43
|
-
Init = -> { 0 }
|
|
44
|
-
|
|
45
|
-
# View: What does the user see?
|
|
46
|
-
View = -> (model, tui) { tui.paragraph(text: <<~END) }
|
|
47
|
-
Current count: #{model}.
|
|
48
|
-
Press any key to increment.
|
|
49
|
-
Press Ctrl+C to quit.
|
|
50
|
-
END
|
|
51
|
-
|
|
52
|
-
# Update: What happens when things change?
|
|
53
|
-
Update = -> (message, model) {
|
|
54
|
-
if message.ctrl_c?
|
|
55
|
-
Rooibos::Command.exit
|
|
56
|
-
elsif message.key?
|
|
57
|
-
model + 1
|
|
58
|
-
end
|
|
59
|
-
}
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
Rooibos.run(Counter)
|
|
63
|
-
|
|
64
|
-
That's the whole pattern: Model holds state, Init creates it, View renders it,
|
|
65
|
-
and Update changes it. The runtime handles everything else.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
=== Your First Real Application
|
|
71
|
-
|
|
72
|
-
A file browser in sixty lines. It opens files, navigates directories, handles
|
|
73
|
-
errors, styles directories and hidden files differently, and supports vim-style
|
|
74
|
-
keyboard shortcuts. If you can do this much with this little code, imagine how
|
|
75
|
-
easy _your_ app will be to build.
|
|
76
|
-
|
|
77
|
-
require "rooibos"
|
|
78
|
-
|
|
79
|
-
module FileBrowser
|
|
80
|
-
# Model: What state does your app need?
|
|
81
|
-
Model = Data.define(:path, :entries, :selected, :error)
|
|
82
|
-
|
|
83
|
-
Init = -> {
|
|
84
|
-
path = Dir.pwd
|
|
85
|
-
entries = Entries[path]
|
|
86
|
-
Ractor.make_shareable( # Ensures thread safety
|
|
87
|
-
Model.new(path:, entries:, selected: entries.first, error: nil))
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
View = -> (model, tui) {
|
|
91
|
-
tui.block(
|
|
92
|
-
titles: [model.error || model.path,
|
|
93
|
-
{ content: KEYS, position: :bottom, alignment: :right}],
|
|
94
|
-
borders: [:all],
|
|
95
|
-
border_style: if model.error then tui.style(fg: :red) else nil end,
|
|
96
|
-
children: [tui.list(items: model.entries.map(&ListItem[model, tui]),
|
|
97
|
-
selected_index: model.entries.index(model.selected),
|
|
98
|
-
highlight_symbol: "",
|
|
99
|
-
highlight_style: tui.style(modifiers: [:reversed]))]
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
Update = -> (message, model) {
|
|
104
|
-
return model.with(error: ERROR) if message.error?
|
|
105
|
-
model = model.with(error: nil) if model.error && message.key?
|
|
106
|
-
|
|
107
|
-
if message.ctrl_c? || message.q? then Rooibos::Command.exit
|
|
108
|
-
elsif message.home? || message.g? then model.with(selected: model.entries.first)
|
|
109
|
-
elsif message.end? || message.G? then model.with(selected: model.entries.last)
|
|
110
|
-
elsif message.up_arrow? || message.k? then Select[:-, model]
|
|
111
|
-
elsif message.down_arrow? || message.j? then Select[:+, model]
|
|
112
|
-
elsif message.enter? then Open[model]
|
|
113
|
-
elsif message.escape? then Navigate[File.dirname(model.path), model]
|
|
114
|
-
end
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
private # Lines below this are implementation details
|
|
118
|
-
|
|
119
|
-
KEYS = "↑/↓/Home/End: Select | Enter: Open | Esc: Navigate Up | q: Quit"
|
|
120
|
-
ERROR = "Sorry, opening the selected file failed."
|
|
121
|
-
|
|
122
|
-
ListItem = -> (model, tui) { -> (name) {
|
|
123
|
-
modifiers = name.start_with?(".") ? [:dim] : []
|
|
124
|
-
fg = :blue if name.end_with?("/")
|
|
125
|
-
tui.list_item(content: name, style: tui.style(fg:, modifiers:))
|
|
126
|
-
} }
|
|
127
|
-
|
|
128
|
-
Select = -> (operator, model) {
|
|
129
|
-
new_index = model.entries.index(model.selected).public_send(operator, 1)
|
|
130
|
-
model.with(selected: model.entries[new_index.clamp(0, model.entries.length - 1)])
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
Open = -> (model) {
|
|
134
|
-
full = File.join(model.path, model.selected.delete_suffix("/"))
|
|
135
|
-
model.selected.end_with?("/") ? Navigate[full, model] : Rooibos::Command.open(full)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
Navigate = -> (path, model) {
|
|
139
|
-
entries = Entries[path]
|
|
140
|
-
model.with(path:, entries:, selected: entries.first, error: nil)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
Entries = -> (path) {
|
|
144
|
-
Dir.children(path).map { |name|
|
|
145
|
-
File.directory?(File.join(path, name)) ? "#{name}/" : name
|
|
146
|
-
}.sort_by { |name| [name.end_with?("/") ? 0 : 1, name.downcase] }
|
|
147
|
-
}
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
Rooibos.run(FileBrowser)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
=== Batteries Included
|
|
156
|
-
|
|
157
|
-
==== Commands
|
|
158
|
-
|
|
159
|
-
Applications fetch data, run shell commands, and set timers. \Rooibos Commands
|
|
160
|
-
run off the main thread and send results back as messages.
|
|
161
|
-
|
|
162
|
-
<b>HTTP requests:</b>
|
|
163
|
-
|
|
164
|
-
Update = -> (message, model) {
|
|
165
|
-
case message
|
|
166
|
-
in :fetch_users
|
|
167
|
-
[model.with(loading: true), Rooibos::Command.http(:get, "/api/users", :got_users)]
|
|
168
|
-
in { type: :http, envelope: :got_users, status: 200, body: }
|
|
169
|
-
model.with(loading: false, users: JSON.parse(body))
|
|
170
|
-
in { type: :http, envelope: :got_users, status: }
|
|
171
|
-
model.with(error: "HTTP #{status}")
|
|
172
|
-
end
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
<b>Shell commands:</b>
|
|
176
|
-
|
|
177
|
-
Update = -> (message, model) {
|
|
178
|
-
case message
|
|
179
|
-
in :list_files
|
|
180
|
-
Rooibos::Command.system("ls -la", :listed_files)
|
|
181
|
-
in { type: :system, envelope: :listed_files, stdout:, status: 0 }
|
|
182
|
-
model.with(files: stdout.lines.map(&:chomp))
|
|
183
|
-
in { type: :system, envelope: :listed_files, stderr:, status: }
|
|
184
|
-
model.with(error: stderr)
|
|
185
|
-
end
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
<b>Timers:</b>
|
|
189
|
-
|
|
190
|
-
Update = -> (message, model) {
|
|
191
|
-
case message
|
|
192
|
-
in { type: :timer, envelope: :tick, elapsed: }
|
|
193
|
-
[model.with(frame: model.frame + 1), Rooibos::Command.wait(1.0 / 24, :tick)]
|
|
194
|
-
end
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
<b>And more!</b> \Rooibos includes <tt>all</tt>, <tt>batch</tt>, <tt>cancel</tt>,
|
|
198
|
-
<tt>custom</tt>, <tt>exit</tt>, <tt>http</tt>, <tt>map</tt>, <tt>open</tt>,
|
|
199
|
-
<tt>system</tt>, <tt>tick</tt>, and <tt>wait</tt> commands. You can also define
|
|
200
|
-
your own custom commands for complex orchestration.
|
|
201
|
-
|
|
202
|
-
Every command produces a message, and Update handles it the same way.
|
|
203
|
-
|
|
204
|
-
==== Testing
|
|
205
|
-
|
|
206
|
-
\Rooibos makes TUIs so easy to test, you'll save more time by writing tests than
|
|
207
|
-
by not testing.
|
|
208
|
-
|
|
209
|
-
<b>Unit test Update, View, and Init.</b> No terminal needed. Test helpers included.
|
|
210
|
-
|
|
211
|
-
def test_moves_selection_down_with_j
|
|
212
|
-
model = Ractor.make_shareable(FileBrowser::Model.new(
|
|
213
|
-
path: "/", entries: %w[bin exe lib], selected: "bin", error: nil))
|
|
214
|
-
message = RatatuiRuby::Event::Key.new(code: "j")
|
|
215
|
-
|
|
216
|
-
result = FileBrowser::Update.call(message, model)
|
|
217
|
-
|
|
218
|
-
assert_equal "exe", result.selected
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
<b>Style assertions.</b> Draw to a headless terminal, verify colors and modifiers.
|
|
222
|
-
|
|
223
|
-
def test_directories_are_blue
|
|
224
|
-
with_test_terminal(60, 10) do
|
|
225
|
-
model = Ractor.make_shareable(FileBrowser::Model.new(
|
|
226
|
-
path: "/", entries: %w[file.txt subdir/], selected: "file.txt", error: nil))
|
|
227
|
-
widget = FileBrowser::View.call(model, RatatuiRuby::TUI.new)
|
|
228
|
-
|
|
229
|
-
RatatuiRuby.draw { |frame| frame.render_widget(widget, frame.area) }
|
|
230
|
-
|
|
231
|
-
assert_blue(1, 2) # "subdir/" at column 1, row 2
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
<b>System tests.</b> Inject events, run the full app, snapshot the result.
|
|
236
|
-
|
|
237
|
-
def test_selection_moves_down
|
|
238
|
-
with_test_terminal(120, 30) do
|
|
239
|
-
Dir.mktmpdir do |dir|
|
|
240
|
-
FileUtils.touch(File.join(dir, "a"))
|
|
241
|
-
FileUtils.touch(File.join(dir, "b"))
|
|
242
|
-
FileUtils.touch(File.join(dir, "c"))
|
|
243
|
-
|
|
244
|
-
inject_key(:down)
|
|
245
|
-
inject_key(:ctrl_c)
|
|
246
|
-
|
|
247
|
-
# Tests use explicit params to inject deterministic initial state.
|
|
248
|
-
Rooibos.run(
|
|
249
|
-
model: Ractor.make_shareable(FileBrowser::Model.new(
|
|
250
|
-
path: dir, entries: %w[a b c], selected: "a", error: nil)),
|
|
251
|
-
view: FileBrowser::View,
|
|
252
|
-
update: FileBrowser::Update
|
|
253
|
-
)
|
|
254
|
-
|
|
255
|
-
assert_snapshots("selection_moved_down") do |lines|
|
|
256
|
-
title = "┌/tmp/test#{'─' * 107}┐"
|
|
257
|
-
lines.map do |l|
|
|
258
|
-
l.gsub(/┌#{Regexp.escape(dir)}[^┐]*┐/, title)
|
|
259
|
-
end
|
|
260
|
-
end
|
|
261
|
-
end
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
Snapshots record both plain text and ANSI colors. Normalization blocks mask
|
|
266
|
-
dynamic content (timestamps, temp paths) for cross-platform reproducibility.
|
|
267
|
-
Run <tt>UPDATE_SNAPSHOTS=1 rake test</tt> to regenerate baselines.
|
|
268
|
-
|
|
269
|
-
==== Scale Up
|
|
270
|
-
|
|
271
|
-
Large applications decompose into fragments. Each fragment has its own Model,
|
|
272
|
-
View, Update, and Init. Parents compose children. The pattern scales.
|
|
273
|
-
|
|
274
|
-
The Router DSL eliminates boilerplate:
|
|
275
|
-
|
|
276
|
-
module Dashboard
|
|
277
|
-
include Rooibos::Router
|
|
278
|
-
|
|
279
|
-
route :stats, to: StatsPanel
|
|
280
|
-
route :network, to: NetworkPanel
|
|
281
|
-
|
|
282
|
-
keymap do
|
|
283
|
-
key :ctrl_c, -> { Rooibos::Command.exit }
|
|
284
|
-
only when: -> (model) { !model.modal_open } do
|
|
285
|
-
key :q, -> { Rooibos::Command.exit }
|
|
286
|
-
key :s, -> { StatsPanel.fetch_command }
|
|
287
|
-
key :p, -> { NetworkPanel.ping_command }
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
Update = from_router
|
|
292
|
-
|
|
293
|
-
# ... Model, Init, View below
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
Declare routes and keymaps. The router generates Update for you. Use guards to
|
|
297
|
-
ignore keys when needed.
|
|
298
|
-
|
|
299
|
-
==== CLI
|
|
300
|
-
|
|
301
|
-
The <tt>rooibos</tt> command scaffolds projects and runs applications.
|
|
302
|
-
|
|
303
|
-
rooibos new my_app # Generate project structure
|
|
304
|
-
rooibos run # Run the app in current directory
|
|
305
|
-
|
|
306
|
-
Generated apps include tests, type signatures, and a working welcome
|
|
307
|
-
screen with keyboard and mouse support.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
---
|
|
311
|
-
|
|
312
|
-
=== The Ecosystem
|
|
313
|
-
|
|
314
|
-
\Rooibos builds on RatatuiRuby[https://www.ratatui-ruby.dev], a Rubygem built on
|
|
315
|
-
Ratatui[https://ratatui.rs]. You get native performance with the joy of Ruby.
|
|
316
|
-
\Rooibos is one way to manage state and composition. Kit is another.
|
|
317
|
-
|
|
318
|
-
==== Rooibos[https://git.sr.ht/~kerrick/rooibos]
|
|
319
|
-
|
|
320
|
-
Model-View-Update architecture. Inspired by Elm, Bubble Tea, and React +
|
|
321
|
-
Redux. Your UI is a pure function of state.
|
|
322
|
-
|
|
323
|
-
- Functional programming with MVU
|
|
324
|
-
- Commands work off the main thread
|
|
325
|
-
- Messages, not callbacks, drive updates
|
|
326
|
-
|
|
327
|
-
==== {Kit}[https://sr.ht/~kerrick/ratatui_ruby/#chapter-3-the-object-path--kit] (Coming Soon)
|
|
328
|
-
|
|
329
|
-
Component-based architecture. Encapsulate state, input handling, and
|
|
330
|
-
rendering in reusable pieces.
|
|
331
|
-
|
|
332
|
-
- OOP with stateful components
|
|
333
|
-
- Separate UI state from domain logic
|
|
334
|
-
- Built-in focus management & click handling
|
|
335
|
-
|
|
336
|
-
Both use the same widget library and rendering engine. Pick the paradigm
|
|
337
|
-
that fits your brain.
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
---
|
|
341
|
-
|
|
342
|
-
=== Links
|
|
343
|
-
|
|
344
|
-
[Get Started]
|
|
345
|
-
{Getting Started}[https://git.sr.ht/~kerrick/rooibos/tree/trunk/item/doc/getting_started/index.md],
|
|
346
|
-
{Tutorial}[https://git.sr.ht/~kerrick/rooibos/tree/trunk/item/doc/tutorial/index.md],
|
|
347
|
-
{Examples}[https://git.sr.ht/~kerrick/rooibos/tree/trunk/item/examples]
|
|
348
|
-
|
|
349
|
-
[Coming From...]
|
|
350
|
-
{React/Redux}[https://git.sr.ht/~kerrick/rooibos/tree/trunk/item/doc/getting_started/for_react_developers.md],
|
|
351
|
-
{BubbleTea}[https://git.sr.ht/~kerrick/rooibos/tree/trunk/item/doc/getting_started/for_go_developers.md],
|
|
352
|
-
{Textual}[https://git.sr.ht/~kerrick/rooibos/tree/trunk/item/doc/getting_started/for_python_developers.md]
|
|
353
|
-
|
|
354
|
-
[Learn More]
|
|
355
|
-
{Essentials}[https://git.sr.ht/~kerrick/rooibos/tree/trunk/item/doc/essentials/index.md],
|
|
356
|
-
{Scaling Up}[https://git.sr.ht/~kerrick/rooibos/tree/trunk/item/doc/scaling_up/index.md],
|
|
357
|
-
{Best Practices}[https://git.sr.ht/~kerrick/rooibos/tree/trunk/item/doc/best_practices/index.md],
|
|
358
|
-
{Troubleshooting}[https://git.sr.ht/~kerrick/rooibos/tree/trunk/item/doc/troubleshooting/index.md]
|
|
359
|
-
|
|
360
|
-
[Community]
|
|
361
|
-
{Discuss}[https://lists.sr.ht/~kerrick/ratatui_ruby-discuss],
|
|
362
|
-
{Announcements}[https://lists.sr.ht/~kerrick/ratatui_ruby-announce],
|
|
363
|
-
{Bug Tracker}[https://todo.sr.ht/~kerrick/ratatui_ruby],
|
|
364
|
-
{Contribution Guide}[https://man.sr.ht/~kerrick/ratatui_ruby/contributing.md],
|
|
365
|
-
{Code of Conduct}[https://man.sr.ht/~kerrick/ratatui_ruby/code_of_conduct.md]
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
---
|
|
369
|
-
|
|
370
|
-
[Website] https://rooibos.run
|
|
371
|
-
[Source] https://git.sr.ht/~kerrick/rooibos
|
|
372
|
-
[RubyGems] https://rubygems.org/gems/rooibos
|
|
373
|
-
|
|
374
|
-
© 2026 Kerrick Long · Library: LGPL-3.0-or-later · Website: CC-BY-NC-ND-4.0 · Snippets: MIT-0
|
data/Rakefile
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
require "bundler/gem_tasks"
|
|
9
|
-
require "ratatui_ruby/devtools"
|
|
10
|
-
|
|
11
|
-
RatatuiRuby::Devtools.install!
|
|
12
|
-
|
|
13
|
-
# Import project-specific tasks
|
|
14
|
-
Dir.glob("tasks/*.rake").each { |r| import r }
|
|
15
|
-
|
|
16
|
-
task default: %w[lint:fix install:force test lint reuse steep]
|
data/Steepfile
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
4
|
-
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
5
|
-
|
|
6
|
-
target :lib do
|
|
7
|
-
signature "sig"
|
|
8
|
-
check "lib"
|
|
9
|
-
|
|
10
|
-
library "open3"
|
|
11
|
-
|
|
12
|
-
collection_config "rbs_collection.yaml"
|
|
13
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# Forms and Validation
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
By the end of this guide, you will:
|
|
10
|
-
|
|
11
|
-
- Collect multi-field user input in your Model
|
|
12
|
-
- Validate input and store error messages
|
|
13
|
-
- Display inline validation feedback
|
|
14
|
-
- Submit form data via Commands
|
|
15
|
-
|
|
16
|
-
> ⚠️ **This page is a stub.** Help us write it! See the [Documentation Plan](../contributors/documentation_plan.md) and [Style Guide](../contributors/documentation_style.md).
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
**Best Practices:** [Modal Dialogs](./modal_dialogs.md) | [Lists and Tables](./lists_and_tables.md) | [HTTP Workflows](./http_workflows.md) | [Streaming Data](./streaming_data.md) | [Orchestration](./orchestration.md)
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# HTTP Workflows
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
By the end of this guide, you will:
|
|
10
|
-
|
|
11
|
-
- Model loading/success/error states for HTTP requests
|
|
12
|
-
- Implement retry logic with exponential backoff
|
|
13
|
-
- Cache responses to avoid redundant fetches
|
|
14
|
-
- Handle offline/error states gracefully
|
|
15
|
-
|
|
16
|
-
> ⚠️ **This page is a stub.** Help us write it! See the [Documentation Plan](../contributors/documentation_plan.md) and [Style Guide](../contributors/documentation_style.md).
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
**Best Practices:** [Modal Dialogs](./modal_dialogs.md) | [Forms and Validation](./forms_and_validation.md) | [Lists and Tables](./lists_and_tables.md) | [Streaming Data](./streaming_data.md) | [Orchestration](./orchestration.md)
|
data/doc/best_practices/index.md
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# Best Practices
|
|
7
|
-
|
|
8
|
-
Common UI patterns and recipes for Rooibos applications.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## UI Patterns
|
|
13
|
-
|
|
14
|
-
- [**Modal Dialogs**](./modal_dialogs.md) — Overlays, focus capture, result routing
|
|
15
|
-
- [**Forms and Validation**](./forms_and_validation.md) — Multi-field input, error display
|
|
16
|
-
- [**Lists and Tables**](./lists_and_tables.md) — Scrolling, selection, pagination
|
|
17
|
-
|
|
18
|
-
## Data Patterns
|
|
19
|
-
|
|
20
|
-
- [**HTTP Workflows**](./http_workflows.md) — Loading states, retries, caching
|
|
21
|
-
- [**Streaming Data**](./streaming_data.md) — SSE, websockets, incremental updates
|
|
22
|
-
- [**Orchestration**](./orchestration.md) — Parallel commands, sequential flows
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
**Having trouble?** Check out [Troubleshooting](../troubleshooting/common_errors.md).
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# Lists and Tables
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
By the end of this guide, you will:
|
|
10
|
-
|
|
11
|
-
- Implement keyboard-navigable scrolling lists
|
|
12
|
-
- Track selection state in your Model
|
|
13
|
-
- Support pagination for large datasets
|
|
14
|
-
- Link to RatatuiRuby List and Table widgets
|
|
15
|
-
|
|
16
|
-
> ⚠️ **This page is a stub.** Help us write it! See the [Documentation Plan](../contributors/documentation_plan.md) and [Style Guide](../contributors/documentation_style.md).
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
**Best Practices:** [Modal Dialogs](./modal_dialogs.md) | [Forms and Validation](./forms_and_validation.md) | [HTTP Workflows](./http_workflows.md) | [Streaming Data](./streaming_data.md) | [Orchestration](./orchestration.md)
|