ratatui_ruby 1.1.0 → 1.1.1

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.
Files changed (259) hide show
  1. checksums.yaml +4 -4
  2. data/ext/ratatui_ruby/Cargo.lock +1 -1
  3. data/ext/ratatui_ruby/Cargo.toml +1 -1
  4. data/lib/ratatui_ruby/version.rb +1 -1
  5. metadata +1 -255
  6. data/.builds/ruby-3.2.yml +0 -54
  7. data/.builds/ruby-3.3.yml +0 -54
  8. data/.builds/ruby-3.4.yml +0 -54
  9. data/.builds/ruby-4.0.0.yml +0 -54
  10. data/.pre-commit-config.yaml +0 -16
  11. data/.rubocop.yml +0 -10
  12. data/AGENTS.md +0 -147
  13. data/CHANGELOG.md +0 -736
  14. data/README.md +0 -187
  15. data/README.rdoc +0 -302
  16. data/Rakefile +0 -11
  17. data/Steepfile +0 -50
  18. data/doc/concepts/application_architecture.md +0 -321
  19. data/doc/concepts/application_testing.md +0 -193
  20. data/doc/concepts/async.md +0 -190
  21. data/doc/concepts/custom_widgets.md +0 -247
  22. data/doc/concepts/debugging.md +0 -401
  23. data/doc/concepts/event_handling.md +0 -162
  24. data/doc/concepts/interactive_design.md +0 -146
  25. data/doc/contributors/auditing/parity.md +0 -239
  26. data/doc/contributors/design/ruby_frontend.md +0 -448
  27. data/doc/contributors/design/rust_backend.md +0 -434
  28. data/doc/contributors/design.md +0 -11
  29. data/doc/contributors/developing_examples.md +0 -400
  30. data/doc/contributors/documentation_style.md +0 -121
  31. data/doc/contributors/index.md +0 -21
  32. data/doc/contributors/releasing.md +0 -215
  33. data/doc/contributors/todo/align/api_completeness_audit-finished.md +0 -381
  34. data/doc/contributors/todo/align/api_completeness_audit-unfinished.md +0 -200
  35. data/doc/contributors/todo/align/term.md +0 -351
  36. data/doc/contributors/todo/align/terminal.md +0 -647
  37. data/doc/contributors/todo/future_work.md +0 -169
  38. data/doc/contributors/upstream_requests/paragraph_span_rects.md +0 -259
  39. data/doc/contributors/upstream_requests/tab_rects.md +0 -173
  40. data/doc/contributors/upstream_requests/title_rects.md +0 -132
  41. data/doc/custom.css +0 -22
  42. data/doc/getting_started/quickstart.md +0 -291
  43. data/doc/getting_started/why.md +0 -93
  44. data/doc/images/app_all_events.png +0 -0
  45. data/doc/images/app_cli_rich_moments.gif +0 -0
  46. data/doc/images/app_color_picker.png +0 -0
  47. data/doc/images/app_debugging_showcase.gif +0 -0
  48. data/doc/images/app_debugging_showcase.png +0 -0
  49. data/doc/images/app_external_editor.gif +0 -0
  50. data/doc/images/app_login_form.png +0 -0
  51. data/doc/images/app_stateful_interaction.png +0 -0
  52. data/doc/images/verify_quickstart_dsl.png +0 -0
  53. data/doc/images/verify_quickstart_layout.png +0 -0
  54. data/doc/images/verify_quickstart_lifecycle.png +0 -0
  55. data/doc/images/verify_readme_usage.png +0 -0
  56. data/doc/images/widget_barchart.png +0 -0
  57. data/doc/images/widget_block.png +0 -0
  58. data/doc/images/widget_box.png +0 -0
  59. data/doc/images/widget_calendar.png +0 -0
  60. data/doc/images/widget_canvas.png +0 -0
  61. data/doc/images/widget_cell.png +0 -0
  62. data/doc/images/widget_center.png +0 -0
  63. data/doc/images/widget_chart.png +0 -0
  64. data/doc/images/widget_gauge.png +0 -0
  65. data/doc/images/widget_layout_split.png +0 -0
  66. data/doc/images/widget_line_gauge.png +0 -0
  67. data/doc/images/widget_list.png +0 -0
  68. data/doc/images/widget_map.png +0 -0
  69. data/doc/images/widget_overlay.png +0 -0
  70. data/doc/images/widget_popup.png +0 -0
  71. data/doc/images/widget_ratatui_logo.png +0 -0
  72. data/doc/images/widget_ratatui_mascot.png +0 -0
  73. data/doc/images/widget_rect.png +0 -0
  74. data/doc/images/widget_render.png +0 -0
  75. data/doc/images/widget_rich_text.png +0 -0
  76. data/doc/images/widget_scroll_text.png +0 -0
  77. data/doc/images/widget_scrollbar.png +0 -0
  78. data/doc/images/widget_sparkline.png +0 -0
  79. data/doc/images/widget_style_colors.png +0 -0
  80. data/doc/images/widget_table.png +0 -0
  81. data/doc/images/widget_tabs.png +0 -0
  82. data/doc/images/widget_text_width.png +0 -0
  83. data/doc/index.md +0 -34
  84. data/doc/troubleshooting/async.md +0 -4
  85. data/doc/troubleshooting/terminal_limitations.md +0 -131
  86. data/doc/troubleshooting/tui_output.md +0 -197
  87. data/examples/app_all_events/README.md +0 -114
  88. data/examples/app_all_events/app.rb +0 -98
  89. data/examples/app_all_events/model/app_model.rb +0 -159
  90. data/examples/app_all_events/model/event_color_cycle.rb +0 -43
  91. data/examples/app_all_events/model/event_entry.rb +0 -94
  92. data/examples/app_all_events/model/msg.rb +0 -39
  93. data/examples/app_all_events/model/timestamp.rb +0 -56
  94. data/examples/app_all_events/update.rb +0 -75
  95. data/examples/app_all_events/view/app_view.rb +0 -80
  96. data/examples/app_all_events/view/controls_view.rb +0 -54
  97. data/examples/app_all_events/view/counts_view.rb +0 -61
  98. data/examples/app_all_events/view/live_view.rb +0 -72
  99. data/examples/app_all_events/view/log_view.rb +0 -57
  100. data/examples/app_all_events/view.rb +0 -9
  101. data/examples/app_cli_rich_moments/README.md +0 -81
  102. data/examples/app_cli_rich_moments/app.rb +0 -189
  103. data/examples/app_color_picker/README.md +0 -156
  104. data/examples/app_color_picker/app.rb +0 -76
  105. data/examples/app_color_picker/clipboard.rb +0 -86
  106. data/examples/app_color_picker/color.rb +0 -193
  107. data/examples/app_color_picker/controls.rb +0 -92
  108. data/examples/app_color_picker/copy_dialog.rb +0 -168
  109. data/examples/app_color_picker/export_pane.rb +0 -128
  110. data/examples/app_color_picker/harmony.rb +0 -58
  111. data/examples/app_color_picker/input.rb +0 -176
  112. data/examples/app_color_picker/main_container.rb +0 -180
  113. data/examples/app_color_picker/palette.rb +0 -111
  114. data/examples/app_debugging_showcase/README.md +0 -119
  115. data/examples/app_debugging_showcase/app.rb +0 -318
  116. data/examples/app_external_editor/README.md +0 -62
  117. data/examples/app_external_editor/app.rb +0 -344
  118. data/examples/app_login_form/README.md +0 -58
  119. data/examples/app_login_form/app.rb +0 -109
  120. data/examples/app_stateful_interaction/README.md +0 -35
  121. data/examples/app_stateful_interaction/app.rb +0 -328
  122. data/examples/timeout_demo.rb +0 -45
  123. data/examples/verify_quickstart_dsl/README.md +0 -55
  124. data/examples/verify_quickstart_dsl/app.rb +0 -49
  125. data/examples/verify_quickstart_layout/README.md +0 -77
  126. data/examples/verify_quickstart_layout/app.rb +0 -73
  127. data/examples/verify_quickstart_lifecycle/README.md +0 -68
  128. data/examples/verify_quickstart_lifecycle/app.rb +0 -62
  129. data/examples/verify_readme_usage/README.md +0 -49
  130. data/examples/verify_readme_usage/app.rb +0 -42
  131. data/examples/verify_website_managed/README.md +0 -48
  132. data/examples/verify_website_managed/app.rb +0 -36
  133. data/examples/verify_website_menu/README.md +0 -60
  134. data/examples/verify_website_menu/app.rb +0 -84
  135. data/examples/verify_website_spinner/README.md +0 -44
  136. data/examples/verify_website_spinner/app.rb +0 -34
  137. data/examples/widget_barchart/README.md +0 -58
  138. data/examples/widget_barchart/app.rb +0 -240
  139. data/examples/widget_block/README.md +0 -44
  140. data/examples/widget_block/app.rb +0 -258
  141. data/examples/widget_box/README.md +0 -54
  142. data/examples/widget_box/app.rb +0 -255
  143. data/examples/widget_calendar/README.md +0 -48
  144. data/examples/widget_calendar/app.rb +0 -115
  145. data/examples/widget_canvas/README.md +0 -31
  146. data/examples/widget_canvas/app.rb +0 -130
  147. data/examples/widget_cell/README.md +0 -45
  148. data/examples/widget_cell/app.rb +0 -112
  149. data/examples/widget_center/README.md +0 -33
  150. data/examples/widget_center/app.rb +0 -118
  151. data/examples/widget_chart/README.md +0 -50
  152. data/examples/widget_chart/app.rb +0 -220
  153. data/examples/widget_gauge/README.md +0 -50
  154. data/examples/widget_gauge/app.rb +0 -229
  155. data/examples/widget_layout_split/README.md +0 -53
  156. data/examples/widget_layout_split/app.rb +0 -260
  157. data/examples/widget_line_gauge/README.md +0 -50
  158. data/examples/widget_line_gauge/app.rb +0 -219
  159. data/examples/widget_list/README.md +0 -58
  160. data/examples/widget_list/app.rb +0 -382
  161. data/examples/widget_map/README.md +0 -48
  162. data/examples/widget_map/app.rb +0 -95
  163. data/examples/widget_overlay/README.md +0 -45
  164. data/examples/widget_overlay/app.rb +0 -250
  165. data/examples/widget_popup/README.md +0 -45
  166. data/examples/widget_popup/app.rb +0 -106
  167. data/examples/widget_ratatui_logo/README.md +0 -43
  168. data/examples/widget_ratatui_logo/app.rb +0 -104
  169. data/examples/widget_ratatui_mascot/README.md +0 -43
  170. data/examples/widget_ratatui_mascot/app.rb +0 -95
  171. data/examples/widget_rect/README.md +0 -53
  172. data/examples/widget_rect/app.rb +0 -222
  173. data/examples/widget_render/README.md +0 -46
  174. data/examples/widget_render/app.rb +0 -186
  175. data/examples/widget_render/app.rbs +0 -41
  176. data/examples/widget_rich_text/README.md +0 -44
  177. data/examples/widget_rich_text/app.rb +0 -193
  178. data/examples/widget_scroll_text/README.md +0 -46
  179. data/examples/widget_scroll_text/app.rb +0 -109
  180. data/examples/widget_scrollbar/README.md +0 -46
  181. data/examples/widget_scrollbar/app.rb +0 -155
  182. data/examples/widget_sparkline/README.md +0 -51
  183. data/examples/widget_sparkline/app.rb +0 -277
  184. data/examples/widget_style_colors/README.md +0 -43
  185. data/examples/widget_style_colors/app.rb +0 -83
  186. data/examples/widget_table/README.md +0 -57
  187. data/examples/widget_table/app.rb +0 -285
  188. data/examples/widget_tabs/README.md +0 -50
  189. data/examples/widget_tabs/app.rb +0 -183
  190. data/examples/widget_text_width/README.md +0 -44
  191. data/examples/widget_text_width/app.rb +0 -117
  192. data/migrate_to_buffer.rb +0 -145
  193. data/mise.toml +0 -8
  194. data/tasks/autodoc/examples.rb +0 -87
  195. data/tasks/autodoc/member.rb +0 -58
  196. data/tasks/autodoc/name.rb +0 -21
  197. data/tasks/autodoc.rake +0 -21
  198. data/tasks/bump/bump_workflow.rb +0 -49
  199. data/tasks/bump/cargo_lockfile.rb +0 -21
  200. data/tasks/bump/changelog.rb +0 -104
  201. data/tasks/bump/header.rb +0 -32
  202. data/tasks/bump/history.rb +0 -32
  203. data/tasks/bump/links.rb +0 -69
  204. data/tasks/bump/manifest.rb +0 -33
  205. data/tasks/bump/patch_release.rb +0 -19
  206. data/tasks/bump/release_branch.rb +0 -17
  207. data/tasks/bump/release_from_trunk.rb +0 -49
  208. data/tasks/bump/repository.rb +0 -54
  209. data/tasks/bump/ruby_gem.rb +0 -29
  210. data/tasks/bump/sem_ver.rb +0 -44
  211. data/tasks/bump/unreleased_section.rb +0 -73
  212. data/tasks/bump.rake +0 -61
  213. data/tasks/doc/documentation.rb +0 -59
  214. data/tasks/doc/link/file_url.rb +0 -30
  215. data/tasks/doc/link/relative_path.rb +0 -61
  216. data/tasks/doc/link/web_url.rb +0 -55
  217. data/tasks/doc/link.rb +0 -52
  218. data/tasks/doc/link_audit.rb +0 -116
  219. data/tasks/doc/problem.rb +0 -40
  220. data/tasks/doc/source_file.rb +0 -93
  221. data/tasks/doc.rake +0 -905
  222. data/tasks/example_viewer.html.erb +0 -172
  223. data/tasks/extension.rake +0 -14
  224. data/tasks/license/headers_md.rb +0 -223
  225. data/tasks/license/headers_rb.rb +0 -210
  226. data/tasks/license/license_utils.rb +0 -130
  227. data/tasks/license/snippets_md.rb +0 -315
  228. data/tasks/license/snippets_rdoc.rb +0 -150
  229. data/tasks/license.rake +0 -91
  230. data/tasks/lint.rake +0 -170
  231. data/tasks/rbs_predicates/predicate_catalog.rb +0 -52
  232. data/tasks/rbs_predicates/predicate_tests.rb +0 -124
  233. data/tasks/rbs_predicates/rbs_signature.rb +0 -63
  234. data/tasks/rbs_predicates.rake +0 -31
  235. data/tasks/rdoc_config.rb +0 -29
  236. data/tasks/resources/build.yml.erb +0 -60
  237. data/tasks/resources/index.html.erb +0 -141
  238. data/tasks/resources/rubies.yml +0 -7
  239. data/tasks/sourcehut.rake +0 -110
  240. data/tasks/steep.rake +0 -11
  241. data/tasks/terminal_preview/app_screenshot.rb +0 -45
  242. data/tasks/terminal_preview/crash_report.rb +0 -54
  243. data/tasks/terminal_preview/example_app.rb +0 -27
  244. data/tasks/terminal_preview/launcher_script.rb +0 -48
  245. data/tasks/terminal_preview/preview_collection.rb +0 -60
  246. data/tasks/terminal_preview/preview_timing.rb +0 -24
  247. data/tasks/terminal_preview/safety_confirmation.rb +0 -58
  248. data/tasks/terminal_preview/saved_screenshot.rb +0 -56
  249. data/tasks/terminal_preview/system_appearance.rb +0 -13
  250. data/tasks/terminal_preview/terminal_window.rb +0 -138
  251. data/tasks/terminal_preview/window_id.rb +0 -16
  252. data/tasks/terminal_preview.rake +0 -30
  253. data/tasks/test.rake +0 -36
  254. data/tasks/website/index_page.rb +0 -30
  255. data/tasks/website/version.rb +0 -122
  256. data/tasks/website/version_menu.rb +0 -68
  257. data/tasks/website/versioned_documentation.rb +0 -83
  258. data/tasks/website/website.rb +0 -53
  259. data/tasks/website.rake +0 -28
@@ -1,48 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
-
6
- # Map (World Map, Canvas) Example
7
-
8
- [![widget_map](../../doc/images/widget_map.png)](app.rb)
9
-
10
- Demonstrates drawing custom graphics and maps using the standard Braille and Block patterns.
11
-
12
- Standard widgets are great for text, but sometimes you need to draw. The `Canvas` widget gives you a high-resolution coordinate system (x, y) to render shapes, lines, and data visualizations that go beyond the grid.
13
-
14
- ## Features Demonstrated
15
-
16
- - **High-Resolution Drawing**: Using Braille patterns (`⣿`) to effectively double the vertical and horizontal resolution of the terminal.
17
- - **Layers**: Drawing multiple shapes (Map, Circles, Lines) in a specific order.
18
- - **Animation**: Updating coordinates in a loop to create smooth motion.
19
- - **World Map**: Using the built-in `Map` shape for geographic data.
20
-
21
- ## Hotkeys
22
-
23
- - **b**: Cycle Background Color (`background_color`)
24
- - **m**: Cycle Marker Type (`marker`)
25
- - **l**: Toggle Labels (modifies `shapes`)
26
- - **q**: Quit
27
-
28
- ## Usage
29
-
30
- <!-- SPDX-SnippetBegin -->
31
- <!--
32
- SPDX-FileCopyrightText: 2026 Kerrick Long
33
- SPDX-License-Identifier: MIT-0
34
- -->
35
- ```bash
36
- ruby examples/widget_map/app.rb
37
- ```
38
- <!-- SPDX-SnippetEnd -->
39
-
40
- ## Learning Outcomes
41
-
42
- Use this example if you need to...
43
-
44
- - Render geographic data (World, USA, Europe).
45
- - Overlay custom labels and markers on a map.
46
- - Animate visual elements on top of a static background.
47
-
48
- [Read the source code →](app.rb)
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- #--
4
- # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: MIT-0
6
- #++
7
-
8
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
9
- require "ratatui_ruby"
10
-
11
- # An example of the Canvas widget showing a world map and animated shapes.
12
- class WidgetMap
13
- include RatatuiRuby::Widgets
14
-
15
- COLORS = [:black, :blue, :white, nil].freeze
16
- MARKERS = [:braille, :half_block, :dot, :block, :bar, :quadrant, :sextant, :octant].freeze
17
-
18
- # Returns a Canvas view for the map demo with the given circle radius.
19
- #
20
- # +tui+:: The RatatuiRuby::TUI instance.
21
- # +radius+:: The radius of the animated circle.
22
- # +marker+:: The marker type.
23
- # +background_color+:: The background color of the canvas.
24
- # +show_labels+:: Whether to show city labels.
25
- def view(tui, radius, marker = :braille, background_color = nil, show_labels: true)
26
- shapes = [
27
- tui.shape_map(color: :green, resolution: :high),
28
- tui.shape_circle(x: 0.0, y: 0.0, radius:, color: :red),
29
- tui.shape_line(x1: 0.0, y1: 0.0, x2: 50.0, y2: 25.0, color: :yellow),
30
- ]
31
-
32
- if show_labels
33
- shapes += [
34
- tui.shape_label(x: -0.1, y: 51.5, text: "London", style: tui.style(fg: :cyan)),
35
- tui.shape_label(x: 139.7, y: 35.7, text: "Tokyo", style: tui.style(fg: :magenta)),
36
- tui.shape_label(x: -74.0, y: 40.7, text: "New York", style: tui.style(fg: :yellow)),
37
- tui.shape_label(x: -122.4, y: 37.8, text: "San Francisco", style: tui.style(fg: :blue)),
38
- tui.shape_label(x: 151.2, y: -33.9, text: "Sydney", style: tui.style(fg: :green)),
39
- ]
40
- end
41
-
42
- tui.canvas(
43
- shapes:,
44
- x_bounds: [-180.0, 180.0],
45
- y_bounds: [-90.0, 90.0],
46
- marker:,
47
- block: tui.block(title: "World Map ['b' bg, 'm' marker: #{marker}, 'l' labels: #{show_labels ? 'on' : 'off'}]", borders: :all),
48
- background_color:
49
- )
50
- end
51
-
52
- # Runs the map demo loop.
53
- def run
54
- RatatuiRuby.run do |tui|
55
- radius = 0.0
56
- direction = 1
57
- bg_index = 0
58
- marker_index = 0
59
- show_labels = true
60
-
61
- loop do
62
- # Animate the circle radius
63
- radius += 0.5 * direction
64
- if radius > 10.0 || radius < 0.0
65
- direction *= -1
66
- end
67
-
68
- # Define the view
69
- canvas = view(tui, radius, MARKERS[marker_index], COLORS[bg_index], show_labels:)
70
-
71
- tui.draw do |frame|
72
- frame.render_widget(canvas, frame.area)
73
- end
74
-
75
- event = tui.poll_event
76
- case event
77
- in { type: :key, code: "q" } | { type: :key, code: :ctrl_c }
78
- break
79
- in type: :key, code: "b"
80
- bg_index = (bg_index + 1) % COLORS.size
81
- in type: :key, code: "m"
82
- marker_index = (marker_index + 1) % MARKERS.size
83
- in type: :key, code: "l"
84
- show_labels = !show_labels
85
- else
86
- # Ignore other events
87
- end
88
-
89
- sleep 0.05
90
- end
91
- end
92
- end
93
- end
94
-
95
- WidgetMap.new.run if __FILE__ == $PROGRAM_NAME
@@ -1,45 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
- # Overlay Example
6
-
7
- [![](../../doc/images/widget_overlay.png)](app.rb)
8
-
9
- This example demonstrates the `Overlay` composition pattern for layering widgets with depth. Modals, notifications, and floating panels all require stacking widgets on top of each other.
10
-
11
- ## Key Concepts
12
-
13
- - **Layer Composition:** Rendering widgets in order creates visual depth — later renders appear "on top."
14
- - **Clear Widget:** Using `tui.clear` before rendering a modal erases the background, preventing content bleed-through.
15
- - **Dynamic Layer Control:** Toggle the number of visible overlay layers at runtime.
16
- - **Layer Ordering:** Swap which overlay appears in front to demonstrate z-ordering.
17
-
18
- ## Hotkeys
19
-
20
- - `0`/`1`/`2`: Set number of visible overlay layers
21
- - `space`: Swap overlay order (which modal is on top)
22
- - `c`: Toggle Clear widget (on/off)
23
- - `q`: Quit
24
-
25
- ## Usage
26
-
27
- <!-- SPDX-SnippetBegin -->
28
- <!--
29
- SPDX-FileCopyrightText: 2026 Kerrick Long
30
- SPDX-License-Identifier: MIT-0
31
- -->
32
- ```bash
33
- ruby examples/widget_overlay/app.rb
34
- ```
35
- <!-- SPDX-SnippetEnd -->
36
-
37
- ## Learning Outcomes
38
-
39
- Use this example if you need to...
40
-
41
- - Build modal dialogs or confirmation popups.
42
- - Layer notifications over existing content.
43
- - Understand the Clear widget's role in opaque overlays.
44
-
45
- [Read the source code →](app.rb)
@@ -1,250 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- #--
4
- # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: MIT-0
6
- #++
7
-
8
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
9
- require "ratatui_ruby"
10
-
11
- HEADLINES = [
12
- "Scientists Discover New Species of Deep-Sea Octopus Near Hawaii",
13
- "Global Climate Summit Reaches Historic Agreement on Emissions",
14
- "Tech Giant Announces Breakthrough in Quantum Computing Research",
15
- "Local Community Garden Initiative Expands to Ten More Cities",
16
- "Astronomers Detect Unusual Radio Signals from Distant Galaxy",
17
- "New Study Links Mediterranean Diet to Improved Heart Health",
18
- "Electric Vehicle Sales Surge as Battery Technology Improves",
19
- "Ancient Manuscripts Reveal Previously Unknown Trading Routes",
20
- "Renewable Energy Now Powers 40% of National Grid",
21
- "Robotics Team Develops AI System for Disaster Response",
22
- "Archaeological Dig Uncovers Evidence of Early Human Settlement",
23
- "Major Airline Commits to Carbon-Neutral Flights by 2035",
24
- "Breakthrough Treatment Shows Promise for Rare Genetic Disease",
25
- "City Council Approves Expanded Public Transportation Network",
26
- "Marine Biologists Track Migration Patterns of Endangered Whales",
27
- "New App Helps Farmers Optimize Water Usage During Drought",
28
- "International Space Station Extends Mission Timeline to 2030",
29
- "Local Schools Implement Innovative STEM Education Program",
30
- "Wildlife Conservation Efforts Lead to Species Population Recovery",
31
- "Research Team Creates Biodegradable Alternative to Plastic Packaging",
32
- "Historic Theater Restoration Project Nears Completion",
33
- "Cybersecurity Experts Warn of Emerging Online Threats",
34
- "Community Food Bank Serves Record Number of Families This Year",
35
- "Innovative Urban Planning Reduces Traffic Congestion by 30%",
36
- ].freeze
37
-
38
- # Overlay Example
39
- # Demonstrates the Overlay widget for layering widgets with depth.
40
- class WidgetOverlay
41
- def initialize
42
- @layer_count = 2 # Start with 2 layers visible
43
- @swapped = false
44
- @clear = true
45
- end
46
-
47
- def run
48
- RatatuiRuby.run do |tui|
49
- @tui = tui
50
- loop do
51
- tui.draw do |frame|
52
- render(frame)
53
- end
54
- break if handle_input == :quit
55
- sleep 0.05
56
- end
57
- end
58
- end
59
-
60
- private def render(frame)
61
- area = frame.area
62
-
63
- # Split into main area and control panel
64
- layout = @tui.layout_split(
65
- area,
66
- direction: :vertical,
67
- constraints: [
68
- @tui.constraint_fill(1),
69
- @tui.constraint_length(5),
70
- ]
71
- )
72
-
73
- main_area = layout[0]
74
- control_area = layout[1]
75
-
76
- # Render background layer - RSS reader
77
- frame.render_widget(background_layer, main_area)
78
-
79
- # Render upper layers based on layer_count and swap state
80
- if @swapped
81
- render_beta_layer(frame, main_area) if @layer_count >= 2
82
- render_notification_layer(frame, main_area) if @layer_count >= 1
83
- else
84
- render_notification_layer(frame, main_area) if @layer_count >= 1
85
- render_beta_layer(frame, main_area) if @layer_count >= 2
86
- end
87
-
88
- # Render control panel
89
- frame.render_widget(control_panel, control_area)
90
- end
91
-
92
- def background_layer
93
- @background_layer ||= @tui.list(
94
- items: HEADLINES,
95
- block: @tui.block(
96
- title: "RSS Reader",
97
- borders: [:all]
98
- )
99
- )
100
- end
101
-
102
- def render_notification_layer(frame, area)
103
- # Position modal: 20% from top, 60% height, 15% from left, 70% width
104
-
105
- vertical_sections = @tui.layout_split(
106
- area,
107
- direction: :vertical,
108
- constraints: [
109
- @tui.constraint_fill(2),
110
- @tui.constraint_fill(5),
111
- @tui.constraint_fill(3),
112
- ]
113
- )
114
-
115
- horizontal_sections = @tui.layout_split(
116
- vertical_sections[1],
117
- direction: :horizontal,
118
- constraints: [
119
- @tui.constraint_fill(1),
120
- @tui.constraint_fill(5),
121
- @tui.constraint_fill(1),
122
- ]
123
- )
124
-
125
- modal_rect = horizontal_sections[1]
126
-
127
- frame.render_widget(@tui.clear, modal_rect) if @clear
128
-
129
- # Render the modal content
130
- frame.render_widget(
131
- @tui.paragraph(
132
- text: "Your feeds have been updated",
133
- wrap: true,
134
- alignment: :center,
135
- block: @tui.block(
136
- title: "Notification",
137
- borders: [:all],
138
- border_style: @tui.style(fg: :black),
139
- style: @tui.style(bg: :red, fg: :black)
140
- )
141
- ),
142
- modal_rect
143
- )
144
- end
145
-
146
- def render_beta_layer(frame, area)
147
- # Position modal: 30% from top, 40% height, 25% from left, 50% width
148
-
149
- vertical_sections = @tui.layout_split(
150
- area,
151
- direction: :vertical,
152
- constraints: [
153
- @tui.constraint_fill(3),
154
- @tui.constraint_fill(4),
155
- @tui.constraint_fill(2),
156
- ]
157
- )
158
-
159
- horizontal_sections = @tui.layout_split(
160
- vertical_sections[1],
161
- direction: :horizontal,
162
- constraints: [
163
- @tui.constraint_fill(2),
164
- @tui.constraint_fill(3),
165
- @tui.constraint_fill(2),
166
- ]
167
- )
168
-
169
- modal_rect = horizontal_sections[1]
170
-
171
- frame.render_widget(@tui.clear, modal_rect) if @clear
172
-
173
- # Render the modal content
174
- frame.render_widget(
175
- beta_paragraph,
176
- modal_rect
177
- )
178
- end
179
-
180
- def beta_paragraph
181
- @beta_paragraph ||= @tui.paragraph(
182
- text: "Thank you for being a beta tester. To give feedback, shout very loudly and we will hear you. Be careful not to scare the llamas.",
183
- wrap: true,
184
- alignment: :left,
185
- block: @tui.block(
186
- title: "Beta Program",
187
- borders: [:all],
188
- border_style: @tui.style(fg: :black),
189
- style: @tui.style(bg: :blue, fg: :black)
190
- )
191
- )
192
- end
193
-
194
- def control_panel
195
- bold_underline = @tui.style(modifiers: [:bold, :underlined])
196
-
197
- first_controls = [
198
- @tui.text_span(content: "0", style: bold_underline),
199
- @tui.text_span(content: "/"),
200
- @tui.text_span(content: "1", style: bold_underline),
201
- @tui.text_span(content: "/"),
202
- @tui.text_span(content: "2", style: bold_underline),
203
- @tui.text_span(content: ": Change number of overlays | "),
204
- @tui.text_span(content: "space", style: bold_underline),
205
- @tui.text_span(content: ": Swap overlay order"),
206
- ]
207
- second_controls = [
208
- @tui.text_span(content: "c", style: bold_underline),
209
- @tui.text_span(content: ": Toggle clear (currently #{@clear ? 'on' : 'off'})"),
210
- ]
211
- third_controls = [
212
- @tui.text_span(content: "q", style: bold_underline),
213
- @tui.text_span(content: ": Quit"),
214
- ]
215
-
216
- first = @tui.text_line(spans: first_controls)
217
- second = @tui.text_line(spans: second_controls)
218
- third = @tui.text_line(spans: third_controls)
219
-
220
- @tui.paragraph(
221
- text: [first, second, third],
222
- alignment: :center,
223
- block: @tui.block(
224
- title: "Controls",
225
- borders: [:all]
226
- )
227
- )
228
- end
229
-
230
- def handle_input
231
- case @tui.poll_event
232
- in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
233
- :quit
234
- in { type: :key, code: "0" }
235
- @layer_count = 0
236
- in { type: :key, code: "1" }
237
- @layer_count = 1
238
- in { type: :key, code: "2" }
239
- @layer_count = 2
240
- in { type: :key, code: " " }
241
- @swapped = !@swapped
242
- in { type: :key, code: "c" }
243
- @clear = !@clear
244
- else
245
- nil
246
- end
247
- end
248
- end
249
-
250
- WidgetOverlay.new.run if __FILE__ == $PROGRAM_NAME
@@ -1,45 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
-
6
- # Clear (Popup, Modal) Example
7
-
8
- [![widget_popup](../../doc/images/widget_popup.png)](app.rb)
9
-
10
- Demonstrates how to render opaque overlays on top of content.
11
-
12
- Terminal renders are additive. If you draw a new widget over an old one, the background colors might mix if not handled correctly. The `Clear` widget resets the area to default (usually transparent/black) to ensure a clean canvas for popups.
13
-
14
- ## Features Demonstrated
15
-
16
- - **The `Clear` Widget**: Printing spaces over an area to "erase" what was underneath.
17
- - **Centering**: Using `Layout` constraints to perfectly center a block on screen.
18
- - **Style Bleed**: showing what happens when you *don't* use `Clear` (background colors leak through).
19
-
20
- ## Hotkeys
21
-
22
- - **Space**: Toggle Clear Widget (Observe the red background effect when disabled)
23
- - **q**: Quit
24
-
25
- ## Usage
26
-
27
- <!-- SPDX-SnippetBegin -->
28
- <!--
29
- SPDX-FileCopyrightText: 2026 Kerrick Long
30
- SPDX-License-Identifier: MIT-0
31
- -->
32
- ```bash
33
- ruby examples/widget_popup/app.rb
34
- ```
35
- <!-- SPDX-SnippetEnd -->
36
-
37
- ## Learning Outcomes
38
-
39
- Use this example if you need to...
40
-
41
- - Create a modal dialog (Confirm, Alert, Form).
42
- - Implement a dropdown menu that overlays other content.
43
- - Fix visual artifacts where old text shows through new widgets.
44
-
45
- [Read the source code →](app.rb)
@@ -1,106 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- #--
4
- # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: MIT-0
6
- #++
7
-
8
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
9
- require "ratatui_ruby"
10
-
11
- # Popup Example
12
- # Demonstrates the Clear widget for creating opaque popups.
13
-
14
- class WidgetPopup
15
- def initialize
16
- @clear_enabled = false
17
- end
18
-
19
- def run
20
- RatatuiRuby.run do |tui|
21
- loop do
22
- tui.draw do |frame|
23
- render(tui, frame)
24
- end
25
- break if handle_input(tui) == :quit
26
- sleep 0.05
27
- end
28
- end
29
- end
30
-
31
- private def render(tui, frame)
32
- area = frame.area
33
-
34
- # 1. Background: Loud Red Background
35
- # This demonstrates "Style Bleed" where the background color persists
36
- # unless explicitly cleared or overwritten.
37
- background = tui.paragraph(
38
- text: "BACKGROUND RED " * 100,
39
- style: tui.style(bg: :red, fg: :white),
40
- wrap: true
41
- )
42
- frame.render_widget(background, area)
43
-
44
- # 2. Popup Area Calculation
45
- # Center the popup vertically and horizontally
46
- vertical_layout = tui.layout_split(
47
- area,
48
- direction: :vertical,
49
- constraints: [
50
- tui.constraint_percentage(25),
51
- tui.constraint_percentage(50), # 50% height
52
- tui.constraint_percentage(25),
53
- ]
54
- )
55
- popup_area_vertical = vertical_layout[1]
56
-
57
- horizontal_layout = tui.layout_split(
58
- popup_area_vertical,
59
- direction: :horizontal,
60
- constraints: [
61
- tui.constraint_percentage(20),
62
- tui.constraint_percentage(60), # 60% width
63
- tui.constraint_percentage(20),
64
- ]
65
- )
66
- popup_area = horizontal_layout[1]
67
-
68
- # 3. Popup Content
69
- # Without Clear, this will "inherit" the red background from underneath.
70
- popup_text = if @clear_enabled
71
- "✓ Clear is ENABLED\n\nResets background to default\n(Usually Black/Transparent)\n\nPress Space to toggle"
72
- else
73
- "✗ Clear is DISABLED\n\nStyle Bleed: Popup is RED!\n(Inherits background style)\n\nPress Space to toggle"
74
- end
75
-
76
- popup_content = tui.paragraph(
77
- text: popup_text,
78
- alignment: :center,
79
- block: tui.block(
80
- title: "Popup (q to quit, space to toggle)",
81
- borders: [:all]
82
- )
83
- )
84
-
85
- # 4. Render Popup
86
- if @clear_enabled
87
- # With Clear: Resets the style in the popup area before rendering content
88
- frame.render_widget(tui.clear, popup_area)
89
- end
90
-
91
- frame.render_widget(popup_content, popup_area)
92
- end
93
-
94
- private def handle_input(tui)
95
- case tui.poll_event
96
- in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
97
- :quit
98
- in type: :key, code: " "
99
- @clear_enabled = !@clear_enabled
100
- else
101
- nil
102
- end
103
- end
104
- end
105
-
106
- WidgetPopup.new.run if __FILE__ == $0
@@ -1,43 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
-
6
- # Ratatui Logo Example
7
-
8
- [![widget_ratatui_logo](../../doc/images/widget_ratatui_logo.png)](app.rb)
9
-
10
- Demonstrates branding with the official logo widget.
11
-
12
- A polished application often needs an "About" screen or a splash screen. This widget provides the standardized project branding.
13
-
14
- ## Features Demonstrated
15
-
16
- - **RatatuiLogo Widget**: Renders the Ratatui ASCII art logo.
17
- - **Centering**: Techniques for centering fixed-size content in a fluid layout.
18
-
19
- ## Hotkeys
20
-
21
- - **q**: Quit
22
-
23
- ## Usage
24
-
25
- <!-- SPDX-SnippetBegin -->
26
- <!--
27
- SPDX-FileCopyrightText: 2026 Kerrick Long
28
- SPDX-License-Identifier: MIT-0
29
- -->
30
- ```bash
31
- ruby examples/widget_ratatui_logo/app.rb
32
- ```
33
- <!-- SPDX-SnippetEnd -->
34
-
35
- ## Learning Outcomes
36
-
37
- Use this example if you need to...
38
-
39
- - Create a splash screen.
40
- - Add an "About" modal to your application.
41
- - See how to center a widget both vertically and horizontally.
42
-
43
- [Read the source code →](app.rb)