Developing Examples
Guidelines for creating and testing examples in the examples/ directory.
Example Structure
Every interactive example should follow this pattern, living in its own directory:
examples/my_example/app.rb:
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__) require "ratatui_ruby" class MyExampleApp def initialize # Initialize state end def run RatatuiRuby.run do loop do render break if handle_input == :quit end end end private def render # Build and draw UI RatatuiRuby.draw(layout) end def handle_input event = RatatuiRuby.poll_event # Process event, return :quit to exit end end MyExampleApp.new.run if __FILE__ == $PROGRAM_NAME
Naming Convention (Required)
Example classes must follow the naming convention: - Directory: examples/my_example/ (snake_case) - Class: MyExampleApp (PascalCase with App suffix)
The class name is derived from the directory name: my_example â MyExampleApp.
This convention enables the terminal_preview:update rake task to automatically capture terminal output for all examples without maintaining a manual registry.
Terminal Size Constraint
All interactive examples must fit within an 80Ă24 terminal (standard VT100 dimensions). This ensures: - Examples work on minimal terminal configurations - Tests can use the default with_test_terminal size (80x24) - Examples remain discoverable and self-documenting through visible hotkey help
Layout pattern for 80Ă24: - Bottom control panel: Allocate ~5-7 lines at bottom for a full-width control block with hotkey documentation. Style hotkeys with bold and underline to make them discoverable. Use double-space or pipe separators to compress multiple controls per line. This keeps all UI text at full readability while maximizing space for the main content area.
Best practices: - Use descriptive names (e.g., âYellow on Blackâ not âYellowâ) so controls are self-documenting and discoverable. - Style hotkeys visually: Use modifiers: [:bold, :underlined] on hotkey letters to make them stand out from descriptions. Example: i (bold, underlined) followed by Items. - Test early by running the example at 80Ă24 and verifying all content is visible without wrapping, scrolling, or clipping.
Every example must also have an RBS file documenting its public methods:
examples/my_example/app.rbs:
class MyExampleApp # @public def self.new: () -> MyExampleApp # @public def run: () -> void end
Key Requirements
-
Only
runshould be public. All other methods (render,handle_input, helper methods) must be private. This prevents tests from calling internal methods directly. -
Use
RatatuiRuby.runfor terminal management. Never callinit_terminalorrestore_terminaldirectly. Therunblock handles terminal setup/teardown automatically and safely, even if an exception occurs. -
Use keyboard keys to cycle through widget attributes. Users should be able to interactively explore all widget options. Common patterns:
-
Arrow keys: Navigate or adjust values
-
Letter keys: Cycle through styles, modes, or variants. Prefer all lowercase keys to avoid confusion and simplify the UI description.
-
Space: Toggle or select
-
qor Ctrl+C: Quit
-
Naming Conventions for Controls
When documenting hotkeys and cycling options in the UI, use consistent naming:
-
Parameter names: Always match the actual Ruby parameter name. For example:
-
Use âScroll Paddingâ (not âScroll Padâ) for the
scroll_padding:parameter -
Use âHighlight Styleâ (not âHighlightâ) for the
highlight_style:parameter -
Use âRepeat Symbolâ (not âRepeatâ) for the
repeat_highlight_symbol:parameter -
Display names for cycled values: Create a
namefield in your options hash to keep display names paired with values: ââruby @styles = [ { name: âYellow Boldâ, style:RatatuiRuby::Style.new(fg: :yellow, modifiers: [:bold]) }, { name: âBlue on Whiteâ, style:RatatuiRuby::Style.new(fg: :blue, bg: :white) } ]
# In controls: âh: Highlight Style (#{@styles[:name]})â # Outputs: âh: Highlight Style (Yellow Bold)â ââ
This keeps the UI self-documenting and users can see exact parameter names when they read the hotkey help.
Hit Testing with the Cached Layout Pattern
Examples with mouse interaction should implement the Cached Layout Pattern documented in doc/interactive_design.md. The hit_test example demonstrates this pattern.
Testing Examples
Example tests live alongside examples as test_app.rb files in the same directory.
Testing Pattern
examples/my_example/test_app.rb:
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__) require "ratatui_ruby" require "ratatui_ruby/test_helper" require "minitest/autorun" require_relative "app" class TestMyExampleApp < Minitest::Test include RatatuiRuby::TestHelper def setup @app = MyExampleApp.new end def test_initial_render with_test_terminal do inject_key(:q) # Queue quit event @app.run # Run the app loop content = buffer_content.join("\n") assert_includes content, "Expected Text" end end def test_keyboard_interaction with_test_terminal do inject_key("s") # Press 's' to cycle something inject_key(:q) # Then quit @app.run content = buffer_content.join("\n") assert_includes content, "Changed State" end end end
Testing Guidelines
-
Inject events, observe buffer. Tests should only interact through:
-
inject_key/inject_keys/inject_eventfor input -
buffer_contentfor output verification -
Never call internal methods. Donât call
render,handle_input,__send__, or access instance variables withinstance_variable_get. Tests verify behavior through the publicrunmethod. -
Use
inject_key(:q)to exit. All examples should support quitting withq, so inject this as the final event to terminate the loop. -
Assert and refute. When testing which item was clicked/selected, also verify the opposite didnât happen:
ruby assert_includes content, "Left Panel clicked" refute_includes content, "Right Panel clicked" -
Test state cycling. If an example cycles through options (styles, modes, etc.), test that pressing the key actually changes the rendered output.
Widget Attribute Cycling
Examples should demonstrate widget configurability by allowing interactive cycling:
| Widget | Attribute | Key Suggestion |
|---|---|---|
| Tabs | highlight_style | Space |
| Tabs | divider | d |
| Tabs | style | s |
| Block | border_type | Space |
| Block | border_color | c |
| List | highlight_style | Space |
| Sparkline | direction | d |
| Scrollbar | orientation | o |
| Scrollbar | theme | s |
Display the current state in the UI (e.g., in a title or status bar or paragraph) so users can see what changed. Display the hotkey in the UI as well, so users can see how to change it; the hotkey should not disappear as app state changes.