Changelog
All notable changes to this project will be documented in this file. The format is based on Keep a Changelog. This project adheres to Semantic Versioning.
Unreleased
Added
Changed
Fixed
Removed
[1.4.1] - 2026-02-15
Added
Changed
Fixed
-
Precompiled Native Gems: Now support Ruby 3.2, 3.3, 3.4, and 4.0 (previously only 4.0)
Removed
[1.4.0] - 2026-02-15
Added
-
Class-Wide Snapshot Normalization:
TestHelper::Snapshotnow supports anormalize_snapshotstemplate method hook. Override it in your test class to mask dynamic content (timestamps, PIDs, temp paths) across all snapshot assertions without repeating normalization blocks. The hook composes with per-call blocks: the hook runs first, then the block. -
Precompiled Native Gems: Precompiled native gems are now published for Windows (x64-mingw-ucrt), macOS, and Linux, eliminating the need to compile the Rust extension from source.
Changed
Fixed
-
Windows Compilation: Fixed gem compilation failures on Windows caused by clang header errors during Rust extension compilation.
-
GVL Contention in
poll_event:poll_eventnow releases Ruby’s Global VM Lock while waiting for terminal events. Previously, background threads (e.g., those executing shell commands viaOpen3) were starved of the GVL during the blocking poll, causing up to 190× slower subprocess execution in multi-threaded applications. -
Gem Size: Reduced gem size from many MB to hundreds of KB by excluding doc/, examples/, and other development files.
Removed
1.3.0 - 2026-01-27
Added
-
Punctuation Name Predicates:
Event::Keynow supports intuitive name-based predicates for symbol keys. Usetilde?,slash?,backslash?,comma?,period?/dot?,colon?,semicolon?,question?,exclamation?/bang?,at?,hash?/pound?,dollar?,percent?,caret?,ampersand?,asterisk?/star?,underscore?,hyphen?/dash?/minus?,plus?,equals?,pipe?/bar?,lessthan?/lt?,greaterthan?/gt?, bracket predicates (lparen?,rparen?,lbracket?,rbracket?,lbrace?,rbrace?and spelled-out variants likeleft_parenthesis?), and quote predicates (backtick?/grave?,singlequote?/apostrophe?,doublequote?,quote?). Thequote?predicate matches both single and double quotes. Underscore variants (e.g.,at_sign?,less_than?) are handled automatically via method normalization. -
Mouse Event DWIM Predicates:
Event::Mousenow supports platform-neutral button predicates (primary?,secondary?,context_menu?,aux?/auxiliary?), wheel aliases (wheel_up?,wheel_down?,scroll?), movement predicates (moved?,hover?,hovering?,move?), press/release aliases (press?/pressed?,release?/released?), and a drag predicate (dragging?). -
Resize Event DWIM Predicates:
Event::Resizenow supports Unix signal aliases (sigwinch?,winch?,sig_winch?), orientation predicates (landscape?,portrait?), and VT100 terminal size predicates (vt100?,at_least_vt100?,over_vt100?,cramped?,constrained?). -
Focus Event DWIM Predicates:
Event::FocusGainedandEvent::FocusLostnow support symmetric predicates for intuitive focus handling. Both respond tofocus?,blur?,gained?,lost?,active?,inactive?,foreground?, andbackground?with semantically correct boolean values. -
Paste Event DWIM Predicates:
Event::Pastenow supports content predicates (empty?,blank?,multiline?/multi_line?,single_line?/singleline?), clipboard aliases (clipboard?,pasteboard?), and a confirmation predicate (pasted?).
Changed
Fixed
Removed
1.2.0 - 2026-01-25
Added
-
Inline Sync Mode:
SyntheticEvents.inline_sync!enables deterministic ordering of sync events with key events. When enabled,inject_syncroutes through the native event queue andpoll_eventreturnsEvent::Syncin sequence. Runtimes that need ordering guarantees (like Rooibos) should call this at startup.
Changed
Fixed
Removed
1.1.0 - 2026-01-25
Added
-
Terminal Capability Detection: New class methods on
RatatuiRuby::Terminalfor environment-based capability detection before initializing TUI mode: -
Terminal.tty?— checks if stdout is connected to a terminal -
Terminal.dumb?— checks if TERM is explicitly set to “dumb” -
Terminal.no_color?— checks if NO_COLOR environment variable is set (respects the NO_COLOR standard) -
Terminal.force_color?— checks if FORCE_COLOR environment variable is set -
Terminal.interactive?— returns true only when tty? and not dumb? -
Terminal.available_color_count— returns color support level (8, 256, or 65535) via crossterm detection -
Terminal.color_support— convenience method returning:none,:basic,:ansi256, or:truecolor -
Terminal.supports_keyboard_enhancement?— checks for Kitty keyboard protocol support -
Backend.window_size— returns terminal dimensions asBackend::WindowSizewith both character grid (columns_rows) and pixel (pixels) sizes asLayout::Sizeinstances; mirrors upstream Ratatui’sbackend::WindowSizestruct -
Terminal.force_color_output(enable)— globally overrides NO_COLOR detection for--color=alwaysflags -
Alignment Constants: New
RatatuiRuby::Layout::HorizontalAlignmentandRatatuiRuby::Layout::VerticalAlignmentmodules with discoverable constants (LEFT,CENTER,RIGHT,TOP,BOTTOM).Layout::Alignmentis an alias forHorizontalAlignment. Use the constants for IDE discoverability, or continue passing symbols (:left,:center, etc.) directly—both work. -
Frame Count Query:
RatatuiRuby.frame_countreturns the number of frames drawn since terminal initialization. The count starts at 0 when the terminal is created, increments by 1 after each draw, and resets when the terminal is restored and re-initialized. -
Mouse and Resize Symbol Comparison:
Event::MouseandEvent::Resizenow support symbol comparison viato_symand==, matchingEvent::Key. Useevent == :mouse_left_down,event == :scroll_up, orevent == :resizefor cleaner event handling. -
Key Event DWIM Predicates:
Event::Keynow supports alternate predicate forms for disambiguation and case handling. Arrow key aliases (arrow_up?,up_arrow?) distinguish keyboard input fromMouse#up?/Mouse#down?. Thekey_prefix and_keysuffix (key_up?,q_key?) provide explicit key event matching in mixed event contexts. Capital letters match their shifted form naturally (G?matchescode="G"with shift), and uppercase in predicates implies shift (alt_B?matchesalt_shift_B). -
Generated RBS Predicate Declarations: New
rake rbs:predicatestask generates RBS type declarations for all 1,328Event::Keypredicate methods (base keys, modifiers, characters, function keys, and all modifier combinations). Predicates are derived from a single source of truth in Rust FFI.
Changed
Fixed
Removed
1.0.0 - 2026-01-25
Added
Changed
Fixed
-
back_tab? DWIM:
back_tab?andbacktab?predicates now match events with code “back_tab” regardless of whether the shift modifier is explicitly present, since back_tab semantically implies shift. -
Terminal Queries During Draw (Deadlock): Calling
viewport_area,terminal_size,get_cell_at,poll_event,get_cursor_position, orget_viewport_typefrom inside adraw()block previously caused the application to freeze forever. The thread blocked on a Mutex. Ruby’sTimeoutcould not interrupt it. The only recovery waskill -9. These reads now work via a snapshot captured before rendering. -
Terminal Mutations During Draw (Deadlock): Calling
insert_before,set_cursor_position, orresize_terminalfrom inside adraw()block previously caused the same silent freeze. These writes now raiseError::Invariantwith a clear message. -
Nested Draw Calls (Deadlock): Calling
draw()from inside anotherdraw()block previously froze the application. Nested draws now raiseError::Invariant. -
Event Injection During Draw (Deadlock): Calling
inject_test_eventfrom inside adraw()block previously froze the application. Event injection now works correctly during draw. -
TableState Row Navigation Methods: Added missing row navigation methods (
select_next,select_previous,select_first,select_last) that should have been included alongside the column navigation methods added in v0.10.0. These methods matchListState‘s navigation API and are used in theapp_stateful_interactionexample.
Removed
0.10.3 - 2026-01-16
Added
-
Rect Destructuring:
Rectobjects now support array destructuring (implementation ofto_ary), allowing intuitive assignment likex, y, w, h = rect. -
Global State Test Helpers: New
RatatuiRuby::TestHelper::GlobalStatemodule (automatically included inTestHelper) provideswith_argvandwith_envmethods for safely testing code that readsARGVorENV.
Changed
-
New Website:
RatatuiRubynow has a home on the world wide web at www.ratatui-ruby.dev. -
A New Way to Browse Examples: You can now browse the source code of the example applications in our documentation site. See AppAllEvents for an example.
-
API Documentation on the Web: RatatuiRuby’s extensive RDoc documentation is now available on the web.
-
Guides on the Web: RatatuiRuby’s in-depth guides are now available on the web.
-
Versioned Examples, API Documentanion, and Guides: API reference, guides, and examples are available on our website for current and past versions of ratatui_ruby, including the trunk version. Visit www.ratatui-ruby.dev/docs to browse.
Fixed
-
Dependency Problems: Removed the unused
ostructdependency from the gemspec. Addedrexmlas an explicit dependency. -
Lazy REXML Loading:
RatatuiRuby::Labs::A11ynow requiresrexmllazily, preventing it from slowing down startup for users not using accessibility features.
0.10.2 - 2026-01-14
Added
-
Experimental Labs System: New
RatatuiRuby::Labsmodule for opt-in experimental features viaRR_LABSenvironment variable. Check withLabs.enabled?(:a11y)or enable programmatically withLabs.enable!(:a11y). Labs are subject to change even between patch releases. -
A11Y Widget Tree Export (Lab): When
RR_LABS=A11Yis set, the widget tree is serialized to XML and written toDir.tmpdir/ratatui_a11y.xmlevery frame. This exports semantic structure (<Paragraph>,<List>, etc.) for accessibility tooling integration. Access is throughRatatuiRuby::Labs::A11y.dump_widget_tree(widget)or automatic viaRatatuiRuby.draw. -
Inline Viewport: New
viewport:parameter forinit_terminalandrunaccepts:inlineor:fullscreen(default). Inline viewports occupy a fixed number of lines at the terminal bottom, preserving scrollback history above. Passheight:to specify inline viewport height (default: 8 lines). Fullscreen viewports use the alternate screen as before. -
Insert Before: New
insert_before(height, widget)method inserts content above an inline viewport into scrollback without disrupting the running TUI. Essential for logging status updates, progress messages, or diagnostic output while your inline TUI continues running. Only works with inline viewports; raisesError::Invariantin fullscreen mode. -
Terminal Area Accessors: New methods to query terminal and viewport dimensions:
-
terminal_area/get_terminal_size— full terminal backend size (always full dimensions) -
viewport_area/get_viewport_area— current viewport rendering area (inline viewport height or full terminal in fullscreen) -
Aliases:
terminal_size,viewport_size,get_terminal_area,get_viewport_size -
Cursor Position Accessors: New methods for querying and setting cursor position:
-
cursor_position/get_cursor_position— returns current cursor position asLayout::Positionor[x, y]array -
cursor_position=/set_cursor_position— sets cursor position fromLayout::Position, array, or separate x/y arguments -
Error::Internal Exception: New exception class for framework bugs, distinct from user errors. If you encounter this, please report it as a framework bug.
Changed
Fixed
Removed
0.10.1 - 2026-01-11
Added
Changed
Fixed
-
poll_event Return Type: Fixed
poll_eventincorrectly returningnilfor unknown event types. The method now correctly returnsEvent::Noneas per its contract.
Removed
0.10.0 - 2026-01-10
Added
-
Table Integer Width Shorthand:
Tablewidths:parameter now accepts plain integers as shorthand forConstraint.length(n). This enables cleaner table definitions likewidths: [40, 16, 10]instead of verbose constraint arrays. Constraints and integers can be mixed freely. -
Error Message Context: Type errors from the Rust backend now include the
inspectstring of the value that caused the error, making debugging significantly easier. For example, “expected array for rows” now shows “expected array for rows, got {title: "Processes", …}”. -
Steep Type Checking: Integrated Steep static type analyzer with a new
rake steeptask. The Steepfile coverslib/with comprehensive RBS type definitions for all widgets, layout primitives, events, and interfaces. -
RBS Type Definitions: Added 50+ RBS signature files in
sig/ratatui_ruby/covering all widget classes, core interfaces (_RectLike,_ToS), type aliases (style_input,widget), and aData.definepatch forsuper()call compatibility. -
Duck Typing Documentation: New
test/test_duck_typing.rbdocuments thatLayout.splitaccepts any object responding tox,y,width,height(Struct, Data.define, custom classes), not justRect. -
Debug Mode: New
RatatuiRuby::Debugmodule controls Rust backtrace visibility for easier debugging. Activate via: -
RUST_BACKTRACE=1— Rust backtraces only -
RR_DEBUG=1— full debug mode (backtraces + future Ruby-side features) -
include RatatuiRuby::TestHelper— auto-enables debug mode in tests -
RatatuiRuby.debug_mode!— programmatic activation -
Debug.test_panic!: New method that intentionally triggers a Rust panic, allowing developers to verify their backtrace setup is working correctly before encountering a real bug.
-
Deferred Panic Backtraces: Rust backtraces during TUI sessions are now stored and printed after terminal restoration, preventing output from being lost on the alternate screen. Previously, panic output in raw terminal mode was invisible.
-
Remote Debugging: Debug mode now integrates with Ruby’s
debuggem for remote debugging.RR_DEBUG=1stops at startup and waits for debugger attachment.RatatuiRuby.debug_mode!continues running in nonstop mode. Attach from another terminal withrdbg --attach. -
Debug.suppress_debug_mode: New block method temporarily suppresses Ruby-side debug checks within its block. Rust backtraces remain enabled. Useful for testing production behavior in debug mode environments.
-
DWIM Hash Coercion: All widget factory methods now accept both
tui.table(hash)andtui.table(**hash)calling styles. When a bare Hash is passed as the first positional argument, it is automatically splatted into keyword arguments. Unknown keys are silently ignored in production mode; in debug mode (RR_DEBUG=1), they raiseArgumentErrorfor early typo detection. -
Ratatui-Aligned Text Methods: New methods on
Text::SpanandText::Linematching Ratatui’s API for style manipulation: -
Span#width— display width in terminal cells (unicode-aware) -
Span.raw(content)— factory for unstyled spans -
Span#patch_style(style)— merge style onto existing style -
Span#reset_style— clear all styling -
Line#left_aligned,Line#centered,Line#right_aligned— fluent alignment setters -
Line#push_span(span)— append span (returns new Line, immutable) -
Line#patch_style(style),Line#reset_style— style manipulation for all spans -
List Query Methods: New methods on
Listmatching Ratatui’s API: -
List#len— number of items (with Ruby aliaseslength,size) -
TableState Navigation Methods: New methods on
TableStatematching Ratatui’s API for column navigation: -
selected_cell— returns[row, column]tuple when both are selected -
with_selected_cell(cell)— constructor to create state with both row and column selected -
select_next_column— select the next column (or first if none selected) -
select_previous_column— select the previous column (saturates at 0) -
select_first_column— select column 0 -
select_last_column— select the last column (clamped during rendering) -
Buffer Query Methods: New module methods on
Buffermatching Ratatui’s API for buffer inspection: -
Buffer.content— returns all cells as an array -
Buffer.get(x, y)— returns the Cell at the specified position -
Buffer.index_of(x, y)— converts position to linear buffer index -
Buffer.pos_of(index)— converts linear index to position coordinates -
Rect Conversion Methods: New methods on
Rectfor extracting geometry components: -
Rect#as_position— returns aPositionobject containing x and y coordinates -
Rect#as_size— returns aSizeobject containing width and height -
Position and Size Classes: New layout primitives matching Ratatui’s API:
-
Layout::Position— represents terminal coordinates (x, y) -
Layout::Size— represents terminal dimensions (width, height) -
Constraint#apply: Computes the constrained size for a given available space. For example,
Constraint.percentage(50).apply(100)returns50. Also aliased ascallfor proc-like invocation (constraint.(100)). -
Color Module: New
Style::Colormodule with constructors matching Ratatui’s API: -
Color.from_u32(0xRRGGBB)— creates a color from a hex integer (aliased asColor.hex) -
Color.from_hsl(h, s, l)— creates a color from HSL values (aliased asColor.hsl) -
Ruby-Idiomatic Aliases: All new APIs include shorter, more Ruby-ish aliases following TIMTOWTDI:
-
Rect#position(alias foras_position),Rect#size(alias foras_size) -
Buffer[x, y](alias forBuffer.get) -
Constraint#call(alias forapply, enablesconstraint.(n)syntax) -
Layout Margin and Spacing:
Layoutnow supportsmargin:andspacing:parameters for edge insets and gaps between segments, matching Ratatui’s Layout API. -
Layout.split_with_spacers: New class method returns both content segments and spacer Rects, enabling custom rendering of dividers or separators between layout sections.
-
Canvas#get_point: Converts canvas coordinates to normalized [0.0, 1.0] grid coordinates for hit testing. Returns
nilfor out-of-bounds coordinates. Also aliased aspointand[]for Ruby-idiomatic access. -
Row#enable_strikethrough: Returns a new Row with
:crossed_outmodifier for indicating cancelled or deleted items. Also aliased asstrikethrough. Note: Strikethrough (SGR 9) is not supported by all terminals; macOS Terminal.app notably lacks support while Kitty, iTerm2, Alacritty, and WezTerm render it correctly. -
Rect Geometry Methods: New methods on
Rectfor geometry manipulation: -
Rect#outer(margin)— expands a rectangle by a margin (inverse ofinner) -
Rect#resize(size)— changes dimensions while preserving top-left position -
Rect#centered_horizontally(constraint)— centers horizontally using Layout -
Rect#centered_vertically(constraint)— centers vertically using Layout -
Rect#centered(h, v)— centers on both axes -
TUI Shape Aliases (DWIM): Canvas shape factories now have terse and bidirectional aliases:
-
Terse:
circle(),point(),map(),label()(shorter forms ofshape_*) -
Bidirectional:
circle_shape(),point_shape(),rectangle_shape(),map_shape(),label_shape()(same asshape_*) -
Note: Terse
rectangleis intentionally excluded to avoid confusion withLayout::Rect; useshape_rectangle()orrectangle_shape(). -
TUI
itemAlias:tui.item(...)is now an alias fortui.list_item(...), providing a terser API when building lists. -
Gauge and LineGauge
percent: Both widgets now have apercentreader that returns the ratio as an integer percentage (0-100).LineGaugealso now accepts apercent:constructor parameter matchingGauge. -
List#selected_item: Returns the item at the selected index (or nil if nothing is selected).
-
Style
underline_color: New optional parameter forStylethat sets a distinct underline color independent of the foreground color. Useful for styling like “white text with red underline”. Terminals must support the underline color extension (SGR 58). -
Style
remove_modifiers: New optional parameter forStylethat explicitly removes modifiers when styles are patched/inherited. Corresponds to Ratatui’ssub_modifierfield. Use it to prevent inherited bold, italic, or other modifiers from propagating. -
Symbols::Shade Constants: New
RatatuiRuby::Symbols::Shademodule exposes Ratatui’s shade block characters as named constants:EMPTY(“ ”),LIGHT(“░”),MEDIUM(“▒”),DARK(“▓”),FULL(“█”). Use them for gradients, density fills, or custom progress indicators. -
Symbols::Line Constants and Sets: New
RatatuiRuby::Symbols::Linemodule exposes Ratatui’s box-drawing characters with 36 individual constants (VERTICAL, HORIZONTAL, corners, T-junctions, cross) and 4 predefined sets:NORMAL(standard corners),ROUNDED(rounded corners),DOUBLE(double-line),THICK(heavy lines). Use them for custom borders or drawing. -
Symbols::Bar Constants and Sets: New
RatatuiRuby::Symbols::Barmodule exposes Ratatui’s vertical bar characters (lower blocks) with 8 individual constants and 2 predefined sets:NINE_LEVELS(full resolution) andTHREE_LEVELS(simplified). Used by Sparkline widget. -
Symbols::Block Constants and Sets: New
RatatuiRuby::Symbols::Blockmodule exposes Ratatui’s horizontal block characters (left blocks) with 8 individual constants and 2 predefined sets:NINE_LEVELS(full resolution) andTHREE_LEVELS(simplified). Used by Gauge widget. -
Symbols::Scrollbar Sets: New
RatatuiRuby::Symbols::Scrollbarmodule exposes 4 predefined scrollbar symbol sets:VERTICAL,DOUBLE_VERTICAL,HORIZONTAL,DOUBLE_HORIZONTAL. Each set containstrack,thumb,begin_char, andend_charsymbols. -
Cell
underline_color:Buffer::Celland top-levelCellnow exposeunderline_colorattribute for introspecting styled underline colors during testing.
Changed
-
tui.drawArgument Validation (Breaking):tui.drawnow validates its arguments. Callingdrawwith neither a tree nor a block raisesArgumentError, as does calling it with both. Previously this produced undefined behavior. -
Layout.splitStricter Type Checking (Breaking):Layout.splitnow rejects invalidareaarguments with a clearArgumentErrorinstead of silently misbehaving. Objects must be aRect,Hashwith:x/:y/:width/:heightkeys, or respond to all four geometry methods. -
Schema Directory Removed (Breaking): The legacy
lib/ratatui_ruby/schema/directory has been removed. All widget classes now live exclusively in their proper namespaces (Widgets::,Layout::,Text::, etc.). Direct usage likeRatatuiRuby::Paragraph(withoutWidgets::) is no longer supported. UseRatatuiRuby::Widgets::Paragraphor the TUI facade (tui.paragraph). -
Buffer::Cell Modifiers (Breaking):
Buffer::Cell#modifiersandCell#modifiersnow return an array ofSymbols (e.g.,[:bold, :italic]) instead ofStrings. This unifies the API, asStylemodifiers were already symbols. Code expecting strings (e.g.cell.modifiers.include?("bold")) must be updated to use symbols. This changes behavior established in v0.9.1.
Fixed
-
Tabs Padding Coercion:
Tabspadding_leftandpadding_rightnow correctly coerce duck-typed integer values (objects responding toto_int/to_i) viaInteger(). Previously these parameters were passed through without coercion, inconsistent with other integer parameters.Text::Linevalues are still accepted as-is for styled padding.
Removed
-
NullIO Re-export (Breaking): Removed
RatatuiRuby::NullIOconstant. UseRatatuiRuby::OutputGuard::NullIOif you were relying on this internal class. -
Legacy Media Keys (Breaking): Removed support for legacy unprefixed media keys (e.g.
play,stop) in event parsing. You must now use the canonicalmedia_-prefixed keys (e.g.media_play,media_stop). Theplay?/stop?predicates still work for both, checking the correct canonical codes.
0.9.1 - 2026-01-08
Added
-
Constraint Batch Constructors:
Constraintnow provides batch factory methods matching upstream Ratatui for creating constraint arrays in a single call: -
from_lengths([10, 20, 10])— create multiple Length constraints -
from_percentages([25, 50, 25])— create multiple Percentage constraints -
from_mins([5, 10, 5])— create multiple Min constraints -
from_maxes([20, 30, 40])— create multiple Max constraints -
from_fills([1, 2, 1])— create multiple Fill constraints -
from_ratios([[1, 4], [2, 4], [1, 4]])— create multiple Ratio constraints -
Async Synchronization: New
Event::Syncevent andSyntheticEventsmodule enable deterministic testing of async behavior: -
Event::Sync— synthetic event that signals runtimes (Tea, Kit) to wait for pending async operations before continuing -
RatatuiRuby::SyntheticEvents— thread-safe Ruby-only queue for synthetic events; runtimes check this alongside native events -
inject_synctest helper — injects a Sync event for deterministic async testing
Changed
Fixed
Removed
0.9.0 - 2026-01-08
Added
-
State Query Predicates (DWIM DX): Widgets now provide ergonomic predicate methods for querying selection and completion state:
-
List#selected?— returns true if an item is selected -
List#empty?— returns true if the list has no items -
Table#row_selected?,Table#column_selected?,Table#cell_selected?— check selection state -
Table#empty?— returns true if the table has no rows -
Gauge#filled?,Gauge#complete?— check progress state (ratio > 0, ratio >= 1.0) -
LineGauge#filled?,LineGauge#complete?— same as Gauge -
Symbol Constants (DWIM DX): Widgets now expose constants for enum-style parameters, enabling IDE autocomplete and self-documenting code:
-
List::HIGHLIGHT_ALWAYS,HIGHLIGHT_WHEN_SELECTED,HIGHLIGHT_NEVER -
List::DIRECTION_TOP_TO_BOTTOM,DIRECTION_BOTTOM_TO_TOP -
Table::HIGHLIGHT_*— same as List -
Table::FLEX_LEGACY,FLEX_START,FLEX_CENTER,FLEX_END,FLEX_SPACE_BETWEEN,FLEX_SPACE_AROUND,FLEX_SPACE_EVENLY -
Layout::Layout::DIRECTION_VERTICAL,DIRECTION_HORIZONTAL -
Layout::Layout::FLEX_*— same as Table -
TUI API Aliases (DWIM DX): The TUI facade now provides CSS-inspired constraint aliases for cleaner layout code:
-
fixed(n)— alias forconstraint_length(n) -
percent(n)— alias forconstraint_percentage(n) -
flex(n)/fr(n)— aliases forconstraint_fill(n)(Flexbox/Grid-inspired) -
split(...)— alias forlayout_split(...) -
ListState Navigation Methods:
ListStatenow provides ergonomic navigation methods matching upstream Ratatui: -
select_next— select the next item (or first if nothing selected) -
select_previous— select the previous item (or last if nothing selected) -
select_first— jump to the first item -
select_last— jump to the last item -
Rect Methods:
Rectnow provides edge accessors, size queries, geometry transformations, and iterators from upstream Ratatui: -
left,right,top,bottom— edge coordinates -
area,empty?— size queries -
union(other),inner(margin),offset(dx, dy),clamp(bounds)— geometry transformations -
rows,columns,positions— iterators yielding slices or coordinates
Changed
-
License: Library code (
lib/,sig/) relicensed to LGPL-3.0-or-later for proprietary use. LGPL allows proprietary applications to link against the library while keeping library modifications open source. -
License: Documentation code snippets now use MIT-0, letting users copy example code without attribution requirements.
Fixed
Removed
-
assert_snapshot: Removed deprecated test helper. Useassert_plain_snapshotorassert_snapshotsinstead. -
Block#border_color: Removed deprecated parameter. Useborder_style: Style.new(fg: color)for equivalent functionality. -
LineChart: Removed deprecated widget. UseChartwithDataset.new(graph_type: :line)instead. Seeexamples/widget_chart/for usage.
0.8.0 - 2026-01-05
Added
-
Output Guard:
RatatuiRuby.guard_io { }temporarily replaces$stdoutand$stderrwith a null sink, preventing screen corruption from chatty gems. Active whenterminal_active?is true; warns if called outside a session (to catch mistakes); silent no-op in headless mode. -
Headless Mode:
RatatuiRuby.headless!enables batch/CLI mode for apps with--no-tuiflags. When headless,guard_iobecomes a silent no-op andinit_terminal/runraiseError::Invariant. This allows the same code to work in both TUI and non-TUI modes. -
Terminal Safety Hooks:
at_exitandSignal.traphandlers forINTandTERMautomatically restore the terminal if a session is active on unexpected exit. This prevents leaving the terminal in raw mode after Ctrl+C or process termination.
Changed
-
Double
init_terminalNow RaisesError::Invariant(Breaking) Callinginit_terminal,init_test_terminal, orrunwhile a TUI session is already active now raisesError::Invariant. Previously, this was undefined but silently “working” behavior that could cause terminal state corruption. If your code intentionally double-inits, callrestore_terminalfirst.
Fixed
Removed
0.7.4 - 2026-01-05
Added
-
Block Inner Area Calculation:
Block#inner(area)method computes the inner content area given an outerRect, accounting for borders and padding. Essential for layout calculations when you need to know usable space inside a block. -
Deferred Warnings During TUI Sessions: Experimental feature warnings (like
Paragraph#line_count) are now automatically queued during active TUI sessions and flushed to stderr afterrestore_terminal. This prevents warnings from corrupting the TUI display. See doc/troubleshooting/tui_output.md for details on handling terminal output during TUI sessions. -
Session State Tracking:
RatatuiRuby.terminal_active?indicates whether a TUI session is active. Callinginit_terminalorinit_test_terminalwhile a session is already active now raisesError::Invariant. -
Error::Invariant: New error class for state invariant violations (e.g., double-init). Distinct from
Error::Safety(lifetime violations) andError::Terminal(operational I/O failures).
Changed
Fixed
-
Direct Text Rendering:
Text::LineandText::Spancan now be rendered directly as widgets viaframe.render_widget(line, area)without wrapping in aParagraph. Previously, these text primitives were silently ignored when passed torender_widget. -
Text Line Alignment:
Text::Linealignment:parameter is now respected during rendering. Previously, the alignment was ignored and text always rendered left-aligned.
Removed
0.7.3 - 2026-01-04
Added
-
Symbol Shortcuts for
bar_set:SparklineandBarChartnow accept:nine_levels(full 9-character gradient) and:three_levels(simplified empty/half/full) as intuitive shortcuts instead of requiring custom character hashes. -
:half_blockMarker:ChartDatasetnow supports:half_blockmarker for higher resolution rendering using ▀ and ▄ characters. -
assert_snapshotsMethod:RatatuiRuby::TestHelper#assert_snapshots(plural) calls bothassert_plain_snapshotandassert_rich_snapshotwith the same name, generating both.txtand.ansifiles for documentation and display purposes. -
Edge-Center Legend Positions:
Chartlegend_positionnow accepts:top,:bottom,:left, and:rightin addition to the existing corner positions (:top_left,:top_right,:bottom_left,:bottom_right). -
:resetColor:Stylefgandbgnow accept:resetto explicitly clear any inherited foreground or background color, restoring the terminal’s default.
Changed
Deprecated
-
assert_snapshot: Useassert_snapshots(plural) instead, orassert_plain_snapshotif you only need plain text. The old method name lacked clarity about whether it captured plain text or styled ANSI output.
Fixed
Removed
0.7.2 - 2026-01-04
Added
-
Tabs
padding_leftandpadding_right: Now acceptInteger(for spaces),String, orText::Linefor styled padding content. Previously only acceptedInteger. Passing aLineobject allows colored or decorated padding.
Changed
Fixed
-
Styled Text Parsing: Fixed multiple widgets incorrectly rendering styled text objects as Ruby inspect strings (e.g.,
#<data RatatuiRuby::Text::Span...>) instead of their styled content: -
Tabsdivider: Now correctly rendersText::Spanobjects. -
Tablehighlight_symbol: Now correctly rendersText::Spanobjects. -
BarChartBarGrouplabel: Now correctly rendersText::Lineobjects. -
ChartAxistitle: Now correctly rendersText::Lineobjects. -
ChartAxislabels: Now correctly rendersText::Lineobjects. -
ChartDatasetname: Now correctly rendersText::Lineobjects.
Removed
0.7.1 - 2026-01-03
Added
Changed
Fixed
-
Block Title Styling:
Blocktitlecontentnow correctly rendersText::Lineobjects with styled spans. Previously, passing a styledLineas title content displayed its Ruby inspect representation (e.g.,#<data RatatuiRuby::Text::Line...>) instead of the styled text.
Removed
0.7.0 - 2026-01-03
[!WARNING] v0.7.0 contains significant breaking changes. See the Migration Guide for upgrade instructions.
Added
-
Rich Text in Table Cells:
Tablecells (rows, header, footer) now acceptText::SpanandText::Lineobjects for per-character styling, matching List widget capabilities. -
Row Wrapper: New
Widgets::Rowclass allows applying row-level styling (background color, style) and layout properties (height, top_margin, bottom_margin) to Table rows. Table rows can now be plain arrays orWidgets::Rowobjects. -
Cell Wrapper: New
Widgets::Cellclass wraps table cell content with optional cell-level styling. Distinct fromBuffer::Cellwhich is for buffer inspection. -
Line#width Method:
Text::Linenow has awidthinstance method that calculates the display width in terminal cells using unicode-aware measurement. Useful for layout calculations with rich text. -
render_rich_buffer: New
TestHelper::Snapshot#render_rich_buffermethod returns the terminal buffer as an ANSI-encoded string with escape codes for colors and modifiers. Useful for debugging, custom assertions, or programmatic inspection beyondassert_rich_snapshot.
Changed
-
Namespace Restructure (Breaking): Classes reorganized to match Ratatui’s module hierarchy. See Migration Guide for details:
-
RatatuiRuby::Rect→RatatuiRuby::Layout::Rect -
RatatuiRuby::Constraint→RatatuiRuby::Layout::Constraint -
RatatuiRuby::Paragraph→RatatuiRuby::Widgets::Paragraph -
RatatuiRuby::Block→RatatuiRuby::Widgets::Block -
RatatuiRuby::Table→RatatuiRuby::Widgets::Table -
RatatuiRuby::List→RatatuiRuby::Widgets::List -
(and all other widgets)
-
Session → TUI Rename (Breaking):
RatatuiRuby::Sessionrenamed toRatatuiRuby::TUIto better reflect its role as a facade/DSL. TheTUIclass now uses explicit factory methods (no metaprogramming) for improved IDE autocomplete support. -
Buffer::Cell vs Widgets::Cell (Breaking):
RatatuiRuby::Cell(buffer inspection) renamed toRatatuiRuby::Buffer::Cell. NewRatatuiRuby::Widgets::Celladded for table cell construction. -
Text::Line style field (Breaking):
Text::Linenow accepts astyle:parameter for line-level styling, matching Ratatui’sLinestruct which hasstyle,alignment, andspansfields. -
Table highlight_style → row_highlight_style (Breaking):
Tableparameterhighlight_style:renamed torow_highlight_style:to match Ratatui’s API naming convention.
Fixed
Removed
0.6.0 - 2026-01-03
Added
-
Rich Text Support:
List,Gauge,LineGauge, andBarChartwidgets now accept rich text objects (Text::Span,Text::Line) in addition to plain strings. This enables per-character styling, multi-colored labels, and complex text formatting matching Ratatui 0.30.0 capabilities. -
ListItem Wrapper: New
ListItemdata class allows applying row-level styling (background color) independent of text content.Listitems can now beString,Text::Span,Text::Line, orListItemobjects. -
Non-Blocking Event Polling:
RatatuiRuby.poll_eventnow accepts an optionaltimeout:parameter (Float seconds). Usetimeout: 0.0for non-blocking checks, ortimeout: 0.1for fixed timesteps. Defaults to0.016(16ms) to preserve existing behavior. -
Cursor Positioning:
Frame#set_cursor_position(x, y)sets the terminal’s hardware cursor position. Using this method is essential for input fields where the user expects visual feedback on their cursor location. -
Text Measurement:
RatatuiRuby::Text.width(string)calculates the display width of a string in terminal cells, correctly handling unicode including ASCII (1 cell), CJK full-width characters (2 cells), emoji (typically 2 cells), and zero-width combining marks (0 cells). This is essential for auto-sizing widgets and responsive layouts. Delegates to the same unicode-width logic that Ratatui uses internally. -
Scroll Offset Control:
ListandTablewidgets now accept an optionaloffsetparameter to control the viewport’s scroll position. Use this for passive scrolling (viewing without selection) or calculating click-to-item mappings. When combined with a selection, Ratatui’s natural scrolling may still adjust the viewport to keep the selection visible; set selection tonilfor fully manual scroll control. -
Rect Geometry Helpers:
Rect#intersects?(other)tests whether two rectangles overlap.Rect#intersection(other)returns the overlapping area as a newRect, ornilif disjoint. Essential for viewport clipping and hit testing in component architectures. -
Stateful Rendering:
Frame#render_stateful_widget(widget, area, state)renders widgets with mutable state objects (ListState,TableState,ScrollbarState). State objects persist across frames, enabling scroll offset read-back and selection tracking. Essential for mouse click-to-row hit testing. Precedence rule: State object properties override widget properties (selected_index,offset). -
Full Keyboard Support: Key events now recognize all keys supported by crossterm: function keys (
f1–f24), navigation (home,end,page_up,page_down,insert,delete), locks (caps_lock,scroll_lock,num_lock), system (print_screen,pause,menu), media controls (play,play_pause,track_next, etc.), and individual modifier keys (left_shift,right_control, etc.). Previously unmapped keys returned"unknown"; they now return propersnake_casestrings. -
Key Categories:
Event::Keynow has akindattribute (:standard,:function,:media,:modifier,:system) for logical grouping. Category predicates (media?,system?,function?,modifier?,standard?) enable clean event routing without string parsing. Theunmodified?method is an alias forstandard?. -
Smart Predicates (DWIM): Key predicates now “Do What I Mean” for media keys.
pause?returnstruefor both systempauseandmedia_pausekeys. For strict matching, usemedia_pause?or compareevent.codedirectly. This reduces boilerplate when responding to conceptual actions regardless of input method. -
Modifier Key Predicates: New methods
super?,hyper?, andmeta?check for these modifier keys. Platform aliases are provided forsuper?:command?/cmd?(macOS),win?(Windows), andtux?(Linux). These work for both modifier flags AND individual modifier key events (e.g.,left_super). Additionally,control?aliasesctrl?andoption?aliasesalt?. -
Navigation Aliases: Convenient predicate aliases for common keys:
return?for Enter,back?for Backspace,del?for Delete,ins?for Insert,escape?for Esc,pgup?/pageup?for Page Up,pgdn?/pagedown?for Page Down. The specialreverse_tab?predicate matches both theback_tabkey andshift+tabcombinations. -
Indexed Color Support:
Stylenow supportsIntegervalues forfgandbg, allowing use of the Xterm 256-color palette (0-255). This includes standard ANSI colors (0-15), the 6x6x6 color cube (16-231), and the grayscale ramp (232-255). -
Rich Snapshots:
RatatuiRuby::TestHelper#assert_rich_snapshotvalidates both content and styling by comparing against stored ANSI snapshots. This allows for visual regression testing that respects colors, bold, italics, and other terminal modifiers. -
Semantic Style Assertions: New testing helpers
assert_color(expected, x:, y:),assert_cell_style(x, y, **style), andassert_area_style(area, **style)allow precise verification of terminal cell attributes without full-screen snapshots. Punchy convenience aliases likeassert_fg/assert_bg,assert_bold,assert_italic,assert_underlined, and color-specific assertions (e.g.,assert_red,assert_bg_blue) provide a more natural API for common testing patterns. -
Buffer Debugging:
RatatuiRuby::TestHelper#print_bufferoutputs the current terminal state to STDOUT with full ANSI color support, making it easier to debug rendering issues during test execution.
Changed
-
Frozen Data Objects (Breaking): Events returned by
RatatuiRuby.poll_eventandCellobjects fromRatatuiRuby.get_cell_atare now deeply frozen for Ractor compatibility. Code that mutates these objects (e.g.,event.modifiers << "custom") must copy the data before modifying.Rectwas already frozen. Note:FrameandSessionare I/O handles with side effects and remain intentionally non-shareable. -
Semantic Exceptions (Breaking): Replaced generic
RuntimeErrorwithRatatuiRuby::Error::Terminalfor backend/terminal failures andRatatuiRuby::Error::Safetyfor API contract violations (like usingFrameoutsidedraw). This allows finer-grained error handling but breaks code explicitly rescuingRuntimeError.ArgumentErrorworks as before. -
Media Key Codes (Breaking): All media key codes now use a consistent
media_prefix:play→media_play,stop→media_stop,play_pause→media_play_pause, etc. Code comparing against literal media key strings must be updated. Use the Smart Predicates (play?,stop?) for backward-compatible behavior. -
Key#charReturn Value (Breaking):charnow returnsnilfor non-printable keys (previously returned""). Code relying onevent.char.empty?must change toevent.char.nil?or useevent.text?instead.
Fixed
-
Frame Safety: Calling methods on a
Framestored outside of adrawblock now correctly raises aRatatuiRuby::Error::Safety(subclass ofRatatuiRuby::Error) instead instead of causing undefined behavior or crashes. This ensures memory safety by preventing use-after-free scenarios with the underlying Rust frame.
Removed
0.5.0 - 2026-01-01
Added
Frame API
-
RatatuiRuby.draw { |frame| ... }: New block-based drawing API that yields aFrameobject for explicit widget placement. Enables hit testing without duplicating layout calculations. -
Frame#area: Returns the terminal area as aRect. -
Frame#render_widget(widget, rect): Renders a widget at a specific position. Works with all existing widgets andRectobjects.
Testing
-
RatatuiRuby::TestHelper#inject_mouse: comprehensive mouse event injection helper supporting coordinates, buttons, and modifiers. -
RatatuiRuby::TestHelper#inject_click: Helper for left-click events. -
RatatuiRuby::TestHelper#inject_right_click: Helper for right-click events. -
RatatuiRuby::TestHelper#inject_drag: Helper for mouse drag events. -
RatatuiRuby::TestHelper#assert_screen_matches: Assert that the current terminal content matches a stored golden snapshot.
Session API
-
Convenience Methods:
Sessionnow wraps class methods fromLayout,Constraint, and other schema classes as instance methods (e.g.,layout_splitdelegates toLayout.split,constraint_percentagetoConstraint.percentage). This enables a more fluent API inRatatuiRuby.runblocks.
Changed
Event System
-
Event::None(Breaking):RatatuiRuby.poll_eventnow returnsEvent::Noneinstead ofnilwhen no event is available. This null-object responds safely to all event predicates withfalse. Useevent.none?or pattern-match ontype: :none. Code usingwhile (event = poll_event)must change towhile (event = poll_event) && !event.none?.
Fixed
Session API
-
Missing Convenience Methods: Fixed
Sessionconvenience methods (e.g., bar_chart) being missed by replacing the manual list with automatic runtime introspection of theRatatuiRubymodule.
Removed
0.4.0 - 2025-12-30
Added
Hex Color Support
-
Style:
fgandbgparameters now accept hex color strings (e.g.,"#ff0000"for red). Requires a 24-bit true color capable terminal (Kitty, iTerm2, modern Terminal.app). Terminals without true color support will gracefully fall back to the closest ANSI color.
RatatuiMascot Widget
-
RatatuiMascot: New widget to display the Ratatui mascot (Ferris).
RatatuiLogo Widget
-
RatatuiLogo: New widget to display the Ratatui logo.
Duck-Typed Numeric Coercion
-
All numeric parameters now accept any object that responds to
to_f(for floats) orto_int/to_i(for integers). This provides idiomatic Ruby interoperability withBigDecimal,Rational, and custom numeric types. Uses Ruby’s built-inFloat()andInteger()Kernel methods for proper duck-type handling.
Paragraph Widget
-
alignment: Breaking Change: Renamedaligntoalignmentto match Ratatui 0.30 API.
Custom Widgets
-
Draw Command API: Custom widgets now return an array of
Drawcommands instead of writing to a buffer. UseRatatuiRuby::Draw.string(x, y, string, style)andRatatuiRuby::Draw.cell(x, y, cell)to create draw commands. This eliminates use-after-free bugs by keeping all pointers inside Rust while Ruby works with pure data objects. Breaking: Therendermethod signature changed fromrender(area, buffer)torender(area).
BarChart Widget
-
bar_set: Customize bar characters (digits, symbols, blocks). -
group_gap: Control spacing between groups in grouped bar charts. -
data: Now accepts an Array ofBarGroupobjects, enabling grouped bar charts. -
BarandBarGroup: New schema classes for defining grouped bar data.
Block Widget
-
border_type: Customize border style (:plain,:rounded,:double,:thick,:quadrant_inside,:quadrant_outside). -
border_set: Customize border characters (e.g., digits, symbols). -
border_style: Apply full style support (colors and modifiers) to borders. Takes precedence overborder_color. -
children: Declare child widgets within the block’s area for composable UI structures. -
Multiple
titles: Display multiple titles with individual alignment (:left,:center,:right) and vertical positioning (:top,:bottom). Each title supports its ownstyle. -
title_style: Base style applied to all titles. -
style: Base style applied to the entire block. -
padding: Directional padding via a single integer (uniform) or array of 4 integers ([left, right, top, bottom]). -
line_count(width): (Experimental) Calculate rendered lines (including borders/padding) for a given width. Delegates to Ratatui’s underlying unstableline_count. -
line_width: (Experimental) Calculate minimum width to avoid wrapping (including borders/padding). Delegates to Ratatui’s underlying unstableline_width.
Calendar Widget
-
events: Hash mappingDateobjects toStyleobjects for highlighting specific dates. -
show_month_header: Toggle month header visibility (defaults tofalse). Breaking: Previously always shown. -
show_weekdays_header: Toggle weekday names (Mon, Tue, etc.) visibility (defaults totrue). -
show_surrounding: OptionalStyleto display dates from adjacent months, ornilto hide them.
Chart Widget
-
legend_position: Position legend at:top_left,:top_right,:bottom_left, or:bottom_right(defaults to:top_right). -
hidden_legend_constraints: Array of twoConstraintobjects to hide the legend when chart area is too small. -
Axis:
labels_alignmentto control horizontal alignment (:left,:center,:right) of axis labels. -
Dataset:styleparameter replacescolor, enabling full styling (fg, bg, modifiers) for chart datasets. Breaking:colorparameter removed.
Gauge Widget
-
style: Base style applied to the entire gauge background. -
gauge_style: Style applied specifically to the filled bar. Breaking: Use this instead ofstyleif you want bar coloring;styleno longer defaults toStyle.default. -
percent: Convenience parameter alternative toratiofor initialization. -
use_unicode: Explicitly toggle between unicode blocks and ASCII rendering (defaults totrue).
LineGauge Widget
-
style: Base style applied to the entire gauge area.
List Widget
-
scroll_padding: Number of items to keep visible above and below the selected item during scrolling. -
repeat_highlight_symbol: Whentrue, repeat highlight symbol on each line of multi-line selections. -
highlight_spacing: Control selection column reservation (:always,:when_selected,:never). -
direction: List orientation (:top_to_bottomor:bottom_to_top).
Sparkline Widget
-
absent_value_symbolandabsent_value_style: Customize rendering ofnilvalues (distinct from0). -
direction: Rendering direction (:left_to_rightor:right_to_left). -
bar_set: Customize bar characters.
Table Widget
-
style: Base style applied to the entire table. -
column_spacing: Horizontal spacing between columns. -
footer: Summary rows at the bottom of the table. -
flex: Layout distribution mode (:legacy,:start,:center,:end,:space_between,:space_around,:space_evenly). -
highlight_spacing: Control selection column reservation (:always,:when_selected,:never). -
column_highlight_style: Style applied to the selected column. -
cell_highlight_style: Style applied to the selected cell (intersection of row and column). -
selected_column: Index of the selected column (Integer or nil). -
widths: Now support all constraint types (:max,:fill,:ratio) with full flexibility.
Tabs Widget
-
style: Base style applied to the entire tabs area. -
padding_leftandpadding_right: Horizontal padding around tab titles. -
width: Calculate total width of the tabs (including dividers/padding).
Canvas Widget
-
background_color: Set canvas background color. -
:half_blockmarker: Block-based rendering using half-height blocks. -
:quadrant,:sextant,:octantmarkers: High-resolution pseudo-pixel rendering. -
Shape::Label: Text labels at canvas coordinates with optional styling.
Scrollbar Widget
-
Full styling support:
thumb_style,track_symbol,track_style,begin_symbol,begin_style,end_symbol,end_style,style. -
All orientation variants:
:vertical_left,:vertical_right,:horizontal_top,:horizontal_bottom(:verticaland:horizontalremain as aliases).
Layout & Constraints
-
Constraint.ratio(numerator, denominator): Proportional constraints with explicit ratio. -
Constraint.fill(weight): Distribute remaining space proportionally. Use multipleFillto split space (e.g.,Fill(1)andFill(3)split 1:3). -
Constraint.max(value): Cap maximum size of a section. -
Layout.split(area, direction:, constraints:, flex:): Compute layout rectangles without rendering, enabling hit testing. -
Flex::SpaceEvenly: New layout mode forLayoutwidget. -
flexparameter: All layout options (:legacy,:start,:center,:end,:space_between,:space_around,:space_evenly).
Rich Text & Text Components
-
Text::SpanandText::Line: Styled text with inline formatting. Combine spans into lines with optional alignment. -
Shapemodule: Canvas shape primitives (Shape::Line,Shape::Circle,Shape::Rectangle,Shape::Point,Shape::Map) to avoid naming conflicts withText::Line.
Event System
-
Typed
EventAPI:RatatuiRuby.poll_eventreturns typed objects (Event::Key,Event::Mouse,Event::Resize,Event::Paste,Event::FocusGained,Event::FocusLost). -
Predicate methods:
key?,mouse?,ctrl?, etc. for cleaner event handling. -
Pattern matching support and discriminator pattern via
type:key in deconstruct_keys. -
Event::Resize: Terminal resize events withwidthandheightattributes. -
Event::Paste: Bracketed paste as atomic event withcontent:. -
Event::FocusGainedandEvent::FocusLost: Terminal focus changes. -
Event::Mouse.newacceptsnilforbuttonparameter (treated as"none").
Geometry & Hit Testing
-
Rect#contains?(x, y): Test whether a point is inside a rectangle. Essential for mouse click handlers. -
Layout.split: Enables calculating widget positions before rendering.
Testing
-
RatatuiRuby::TestHelper#inject_keys: Concise event injection helper. -
RatatuiRuby::TestHelper#get_celland assert_cell_style: Inspect terminal cell attributes (colors, characters). -
with_test_terminal: Default timeout of 2 seconds to prevent hanging tests. Breaking: Default size is now 80×24 (VT100 standard) instead of 20×10. -
Error on
inject_event/inject_keysoutsidewith_test_terminal: Prevents test hangs from race conditions. -
Value equality (
==) forEventobjects: Simplify assertions.
Lifecycle & Application Structure
-
RatatuiRuby.run: New context manager that initializes terminal, yields session, and restores on exit. Allows custom event loop control. -
Session class: Renamed from
DSLto better reflect its purpose as a managed terminal session with convenience methods. -
Focus and Bracketed Paste events: Enabled by default in
RatatuiRuby.runandRatatuiRuby.init_terminal(disable withfocus_events: falseorbracketed_paste: false).
Documentation & Examples
-
Cached Layout Pattern: Documented in
doc/interactive_design.md. Three-phase lifecycle pattern (calculate_layout,render,handle_input) solves layout duplication in immediate-mode UI. Foundation for Component architecture in Gem 1.5.
Changed
-
Calendar: Renamed
day_styletodefault_styleto match Ratatui 0.30 API. This is a breaking change. [Kerrick Long] -
Custom Widget
renderMethod (Breaking): Changed signature fromrender(area, buffer)torender(area), with render methods now returning an array ofDrawcommands instead of writing directly to a buffer. This change improves memory safety by eliminating use-after-free risks. -
Ratatui Upgraded to 0.30.0: Underlying
ratatuilibrary upgraded from 0.29, bringing modularized crates,no_stdsupport for embedded targets, and major widget/layout enhancements. Layout cache explicitly enabled for performance. -
Event API (Breaking):
RatatuiRuby.poll_eventreturns typedEventobjects instead of raw Hashes. Code usingevent[:type]must change toevent.key?,event.code, etc. -
RatatuiRuby.main_loop Removed (Breaking): Removed in favor of
RatatuiRuby.runfor more explicit lifecycle control. -
TestHelper Terminal Size (Breaking):
with_test_terminaldefaults to 80×24 instead of 20×10. -
Calendar Month Header Default (Breaking):
show_month_headerdefaults tofalse(previously always shown). Setshow_month_header: trueif relying on the old behavior. -
Gauge
styleDefault (Breaking): No longer defaults toStyle.default. Usegauge_stylefor bar coloring instead.
Fixed
-
Alpine Linux Support: Fixed gem installation failures on Alpine Linux (musl targets) by properly configuring
crate-typeto support static linking where dynamic linking is unsupported. -
Rust Safety: Convert
class.name()results to owned strings for proper GC safety with Magnus 0.8. -
Terminal Preview Detection: Detect staged changes correctly in preview generation.
0.3.1 - 2025-12-28
Added
-
Ruby 4 Support: Updated magnus FFI bindings to use the modern API for Ruby 4.0.0 compatibility.
0.3.0 - 2025-12-28
Added
-
Custom Widget API (Breaking): Custom widgets that define a
rendermethod now receive onlyarea(notbuffer) and must return an array ofDrawcommands. UseRatatuiRuby::Draw.string(x, y, string, style)andRatatuiRuby::Draw.cell(x, y, cell)instead ofbuffer.set_stringandbuffer.set_cell. This eliminates a class of use-after-free bugs by ensuring Ruby never holds pointers to Rust-owned memory. Widgets can now be unit tested by asserting on the returned array. -
The Escape Hatch (Ruby Render Callback): Added the ability to define custom widgets in pure Ruby by implementing a
render(area, buffer)method. TheBufferobject provides low-level drawing primitives likeset_string, allowing developers to create custom TUI components without writing Rust code. -
Clear Widget: Added the
Clearwidget, which resets the terminal buffer in the area it is rendered. This is essential for creating opaque popups and modals that prevent background styles from “bleeding” through transparent widgets. -
Interactive Table Selection: The
Tablewidget now supports row selection withselected_row,highlight_style, andhighlight_symbolparameters. This enables building interactive data grids and file explorers where users can navigate through rows using keyboard input. -
Scrollable Paragraphs: The
Paragraphwidget now supports ascrollparameter that accepts a(y, x)array to scroll content vertically and horizontally. This enables viewing long text content that exceeds the visible area, such as logs or documents. The parameter order matches ratatui’s convention. -
Enhanced Tabs Customization: The
Tabswidget now supportshighlight_stylefor the selected tab and a customizabledividerstring (defaulting to the standard pipe|). This allows for richer visual feedback in tabbed interfaces.
Changed
-
Center Widget: Removed the implicit
Clearcall from theCenterwidget.Centeris now a pure layout widget, requiring an explicitClearwidget if background clearing is desired. This restores correct behavior for transparent overlays.
0.2.0 - 2025-12-24
Added
-
DSL for Simpler Apps: Introduced
RatatuiRuby.main_loop, a new entrypoint that simplifies application structure when you don’t need control of the event loop or application lifecycle. -
Calendar Widget: Added the
Calendarwidget, allowing you to display monthly views and visualize date-based information. -
Generic Charts: Implemented the full
Chartwidget, which supersedes the now-deprecatedLineChartandBarChartwidgets, giving you more freedom to visualize data sets. -
Enhanced List Styling: You can now customize the appearance of selected items in a
Listusinghighlight_styleandhighlight_symbol. -
Broader Ruby Support: Added support for a wider range of Ruby versions: every non-EOL version. The latest preview of Ruby 4.0 is tested in CI, but not supported.
-
Dev Tools: Added internal Rake tasks for managing historical documentation and SemVer checks.
0.1.0 - 2025-12-22
Added
-
First Release: Initial public release of ratatui_ruby, bringing the power of the Rust ratatui library to Rubyists!
-
Core Widget Set: Includes a comprehensive suite of widgets to get you started:
-
Block,Borders, andParagraphfor basic content. -
ListandTablefor structured data. -
GaugeandSparklinefor progress and metrics. -
Tabsfor navigation. -
Canvasfor drawing shapes (Lines, Circles, Rectangles, Maps). -
Layout System: A flexible layout engine using
Flex,Layout, andConstraintsto build responsive interfaces that adapt to any terminal size. -
Forms & Layers: Primitives like
OverlayandCenterfor creating modal dialogs, plus aCursorwidget for text input interactions. -
Styling: Full support for
Ratatui‘s styling primitives, including modifiers and RGB/ANSI colors. -
Input Handling: Robust handling for both Keyboard and Mouse events.
-
Testing Support: Included
RatatuiRuby::TestHelperand RSpec integration to make testing your TUI applications possible.