Releases: Aaronontheweb/termina
Termina 0.5.1
0.5.1 December 19th 2025
Bug Fixes:
- Fix nullability propagation in [Reactive] source generator (#112)
- Source generator now preserves nullable reference type annotations (e.g.,
string?,int?) in generated properties - Added custom
SymbolDisplayFormatwithIncludeNullableReferenceTypeModifieroption - Nullable fields now generate properties with matching nullability annotations, providing correct nullability hints in consuming code
- Previously, nullable fields like
string? _fieldwould generate non-nullable properties, losing nullability information
- Source generator now preserves nullable reference type annotations (e.g.,
0.5.0 December 18th 2025
New Features:
-
BlockSegment wrapper for block-level streaming text (#108)
- Enables text segments to render as block elements starting on new lines with vertical word wrapping
- New
BlockSegmentclass wraps anyITextSegmentfor block-level rendering - Fluent
.AsBlock()API for creating block segments StreamingTextNodeautomatically detectsBlockSegmentand inserts newlines- Supports both static and animated content (spinners, status indicators)
- Perfect for LLM agent "thinking" displays and streaming content that should update in-place within a fixed area
- Closes #107
-
Page-level key binding system with capture phase (#105)
- Pages can now intercept keyboard input before focused components receive it
- New
PageKeyBindingsclass for registering page-level key handlers - Added
HandlePageInputmethod toIBindablePageinterface TerminaApplication.ProcessEvent()now uses capture phase (page) then bubble phase (focused component)ReactivePageexposesKeyBindingsproperty for navigation key handling- Enables reliable Escape, Tab, and other navigation keys in complex pages
- Closes #104
-
GridNode 2D layout primitive (#100)
- New 2D grid layout enabling consistent column/row sizing across all cells
- Cell addressing via
SetCell(row, col, node)or fluentAddRow()API - Constraint-based sizing for columns and rows (Fixed, Auto, Fill, Percent)
- Grid line rendering with Single, Double, Rounded, and Ascii border styles
- Cell spanning support (
colspanandrowspan) for merged header cells - Focus navigation with 2D arrow key support
- Navigation modes: None, CellNavigation, ChildFocusRouting
- Perfect for dashboards, data tables, and structured layouts
-
TextNode horizontal alignment (#100)
- New
TextAlignmentenum: Left (default), Center, Right - Fluent methods:
Align(),AlignCenter(),AlignRight() - Works seamlessly with GridNode cells and other layout containers
- New
-
Component gallery demo (#103)
- New
Termina.Demo.Galleryproject showcasing UI components - Interactive gallery pages for SelectionList, Grid, and other components
- Run with:
dotnet run --project demos/Termina.Demo.Gallery
- New
Bug Fixes:
-
Fix SelectionListNode number prefixes (#103)
- SelectionListNode now shows number prefixes for all items, not just items 1-9
- Fixes #101
-
Fix SelectionListNode "Other" option auto-start (#103)
- Navigating to "Other" option with arrow keys no longer auto-starts text input
- Text input mode now requires explicit Enter or Space key press
- Fixes #102
-
Fix async test method not awaiting (#109)
- Corrected test method signature to properly await async operations
- Improves test reliability and prevents potential race conditions
0.4.0 December 17th 2025
Breaking Changes:
- VerticalLayout and HorizontalLayout now default to Auto() sizing (#97)
- Previously, these layouts defaulted to Fill(), which caused nested layouts to compete with siblings for space
- New Auto() default means nested layouts size to their content by default
- Fill() is now only needed for children that should claim remaining space within a container
- Root layouts always fill terminal bounds regardless of constraints
- StackLayout retains Fill() as its default since overlays should fill
- Fixes #95
New Features:
-
Rich content support for SelectionListNode (#96)
- New
SelectionItemContentclass for multi-line, styled selection items - Support for
ITextSegment(static and animated) in selection item content - "Other" option with inline text input for custom user responses
- Multi-line items with per-line styling and animated segments (spinners, etc.)
- Proper coordinate translation via sub-context rendering
- New
-
Platform-native console abstraction for event-driven input (#90)
- Replaced polling-based input with platform-native event-driven input on Windows
- Windows console enables VT100/ANSI support via
ENABLE_VIRTUAL_TERMINAL_PROCESSING - Event-driven input via
ReadConsoleInputWeliminates polling latency - Window resize events via
WINDOW_BUFFER_SIZE_EVENT - ~1000x rendering performance improvement on Windows (22-60ms → 0.02-0.08ms per frame)
- Cached console dimensions to avoid repeated P/Invoke calls
- Fallback console for non-Windows platforms with 1ms polling delay
- Closes #78, #79, #81
-
Formalized diagnostic tracing system (#84)
- Lightweight, zero-cost-when-disabled tracing system for debugging TUI applications
- Custom abstraction over Microsoft.Extensions.Logging (no direct dependency required)
- Deferred string formatting via
TraceEventstruct with template and args - Lock-free file output using Channel with single reader pattern
- Category-based filtering (Focus, Layout, Input, Page, Render, etc.)
- Level-based filtering (Trace, Debug, Info, Warning, Error)
- Optional MEL integration via
LoggerTraceListeneradapter - DI extension methods for easy configuration
- Trace logs written to %TEMP%/termina-logs/ with timestamped filenames
- Addresses #72
0.3.0 December 17th 2025
New Features:
- Inline animated text segments with tracked segment support (#71)
- Opt-in tracked segments for
StreamingTextNodeenabling inline animations (spinners, timers, etc.) - Caller-provided
SegmentIdsystem (like HTML div IDs) for tracking and manipulating segments - New interfaces:
ITextSegment,IAnimatedTextSegment,ICompositeTextSegment SpinnerSegmentcomponent with 6 animation styles: Dots, Line, Arrow, Bounce, Box, CircleStaticTextSegmentfor trackable static text- Methods:
AppendTracked(id, segment),Replace(id, segment, keepTracked),Remove(id) - Interface-based message protocol with
IChatMessagefor clean chat operations - Enables any inline animated element (timers, progress bars, blinks, highlighters) with minimal overhead
- Opt-in tracked segments for
Bug Fixes:
-
Fix modal text input not accepting keystrokes (#70, #74)
- Critical fix where
TextInputNodein modal dialogs would be immediately disposed after being focused - Fixed
ReactiveLayoutNodelifecycle to callOnDeactivate()instead ofDispose()when switching children - Fixed modal focus propagation -
ModalNodenow forwardsOnFocused()andOnBlurred()to content - Fixed
ReactiveLayoutNodeto callOnActivate()on new children when they are dynamically swapped in - Fixed render loop invalidation to properly propagate through container hierarchy
- Users can now properly type in modal dialogs without
ObjectDisposedException
- Critical fix where
-
Fix NavigationBehavior.PreserveState layout disposal issue (#67, #69)
- Implemented Active/Inactive State Pattern for layout nodes to prevent
ObjectDisposedExceptionwhen navigating - Added
IActivatableNodeinterface definingOnActivate/OnDeactivatelifecycle methods - Layout nodes now pause/resume instead of dispose/recreate on navigation with PreserveState behavior
ReactivePagenow builds layout once and preserves it across navigationsTextInputNode,SpinnerNode,ReactiveLayoutNode,ConditionalNode,SelectionListNode,ModalNode, andContainerNodeall properly implement lifecycle propagationTerminaApplicationnow properly disposes cached pages viaIDisposableimplementation- Fixes race conditions and ensures proper resource cleanup
- Implemented Active/Inactive State Pattern for layout nodes to prevent
Improvements:
- Add TERMINA002 analyzer and refactor MVVM architecture (#68)
- New Roslyn analyzer (TERMINA002) detects layout nodes incorrectly stored as fields/properties in ViewModels
- Refactored MVVM pattern: ViewModel owns Input (public) for business logic, Page owns Focus for interactive control
- ViewModels now handle keyboard input dir...
Termina 0.5.0
0.5.0 December 18th 2025
New Features:
-
BlockSegment wrapper for block-level streaming text (#108)
- Enables text segments to render as block elements starting on new lines with vertical word wrapping
- New
BlockSegmentclass wraps anyITextSegmentfor block-level rendering - Fluent
.AsBlock()API for creating block segments StreamingTextNodeautomatically detectsBlockSegmentand inserts newlines- Supports both static and animated content (spinners, status indicators)
- Perfect for LLM agent "thinking" displays and streaming content that should update in-place within a fixed area
- Closes #107
-
Page-level key binding system with capture phase (#105)
- Pages can now intercept keyboard input before focused components receive it
- New
PageKeyBindingsclass for registering page-level key handlers - Added
HandlePageInputmethod toIBindablePageinterface TerminaApplication.ProcessEvent()now uses capture phase (page) then bubble phase (focused component)ReactivePageexposesKeyBindingsproperty for navigation key handling- Enables reliable Escape, Tab, and other navigation keys in complex pages
- Closes #104
-
GridNode 2D layout primitive (#100)
- New 2D grid layout enabling consistent column/row sizing across all cells
- Cell addressing via
SetCell(row, col, node)or fluentAddRow()API - Constraint-based sizing for columns and rows (Fixed, Auto, Fill, Percent)
- Grid line rendering with Single, Double, Rounded, and Ascii border styles
- Cell spanning support (
colspanandrowspan) for merged header cells - Focus navigation with 2D arrow key support
- Navigation modes: None, CellNavigation, ChildFocusRouting
- Perfect for dashboards, data tables, and structured layouts
-
TextNode horizontal alignment (#100)
- New
TextAlignmentenum: Left (default), Center, Right - Fluent methods:
Align(),AlignCenter(),AlignRight() - Works seamlessly with GridNode cells and other layout containers
- New
-
Component gallery demo (#103)
- New
Termina.Demo.Galleryproject showcasing UI components - Interactive gallery pages for SelectionList, Grid, and other components
- Run with:
dotnet run --project demos/Termina.Demo.Gallery
- New
Bug Fixes:
-
Fix SelectionListNode number prefixes (#103)
- SelectionListNode now shows number prefixes for all items, not just items 1-9
- Fixes #101
-
Fix SelectionListNode "Other" option auto-start (#103)
- Navigating to "Other" option with arrow keys no longer auto-starts text input
- Text input mode now requires explicit Enter or Space key press
- Fixes #102
-
Fix async test method not awaiting (#109)
- Corrected test method signature to properly await async operations
- Improves test reliability and prevents potential race conditions
0.4.0 December 17th 2025
Breaking Changes:
- VerticalLayout and HorizontalLayout now default to Auto() sizing (#97)
- Previously, these layouts defaulted to Fill(), which caused nested layouts to compete with siblings for space
- New Auto() default means nested layouts size to their content by default
- Fill() is now only needed for children that should claim remaining space within a container
- Root layouts always fill terminal bounds regardless of constraints
- StackLayout retains Fill() as its default since overlays should fill
- Fixes #95
New Features:
-
Rich content support for SelectionListNode (#96)
- New
SelectionItemContentclass for multi-line, styled selection items - Support for
ITextSegment(static and animated) in selection item content - "Other" option with inline text input for custom user responses
- Multi-line items with per-line styling and animated segments (spinners, etc.)
- Proper coordinate translation via sub-context rendering
- New
-
Platform-native console abstraction for event-driven input (#90)
- Replaced polling-based input with platform-native event-driven input on Windows
- Windows console enables VT100/ANSI support via
ENABLE_VIRTUAL_TERMINAL_PROCESSING - Event-driven input via
ReadConsoleInputWeliminates polling latency - Window resize events via
WINDOW_BUFFER_SIZE_EVENT - ~1000x rendering performance improvement on Windows (22-60ms → 0.02-0.08ms per frame)
- Cached console dimensions to avoid repeated P/Invoke calls
- Fallback console for non-Windows platforms with 1ms polling delay
- Closes #78, #79, #81
-
Formalized diagnostic tracing system (#84)
- Lightweight, zero-cost-when-disabled tracing system for debugging TUI applications
- Custom abstraction over Microsoft.Extensions.Logging (no direct dependency required)
- Deferred string formatting via
TraceEventstruct with template and args - Lock-free file output using Channel with single reader pattern
- Category-based filtering (Focus, Layout, Input, Page, Render, etc.)
- Level-based filtering (Trace, Debug, Info, Warning, Error)
- Optional MEL integration via
LoggerTraceListeneradapter - DI extension methods for easy configuration
- Trace logs written to %TEMP%/termina-logs/ with timestamped filenames
- Addresses #72
0.3.0 December 17th 2025
New Features:
- Inline animated text segments with tracked segment support (#71)
- Opt-in tracked segments for
StreamingTextNodeenabling inline animations (spinners, timers, etc.) - Caller-provided
SegmentIdsystem (like HTML div IDs) for tracking and manipulating segments - New interfaces:
ITextSegment,IAnimatedTextSegment,ICompositeTextSegment SpinnerSegmentcomponent with 6 animation styles: Dots, Line, Arrow, Bounce, Box, CircleStaticTextSegmentfor trackable static text- Methods:
AppendTracked(id, segment),Replace(id, segment, keepTracked),Remove(id) - Interface-based message protocol with
IChatMessagefor clean chat operations - Enables any inline animated element (timers, progress bars, blinks, highlighters) with minimal overhead
- Opt-in tracked segments for
Bug Fixes:
-
Fix modal text input not accepting keystrokes (#70, #74)
- Critical fix where
TextInputNodein modal dialogs would be immediately disposed after being focused - Fixed
ReactiveLayoutNodelifecycle to callOnDeactivate()instead ofDispose()when switching children - Fixed modal focus propagation -
ModalNodenow forwardsOnFocused()andOnBlurred()to content - Fixed
ReactiveLayoutNodeto callOnActivate()on new children when they are dynamically swapped in - Fixed render loop invalidation to properly propagate through container hierarchy
- Users can now properly type in modal dialogs without
ObjectDisposedException
- Critical fix where
-
Fix NavigationBehavior.PreserveState layout disposal issue (#67, #69)
- Implemented Active/Inactive State Pattern for layout nodes to prevent
ObjectDisposedExceptionwhen navigating - Added
IActivatableNodeinterface definingOnActivate/OnDeactivatelifecycle methods - Layout nodes now pause/resume instead of dispose/recreate on navigation with PreserveState behavior
ReactivePagenow builds layout once and preserves it across navigationsTextInputNode,SpinnerNode,ReactiveLayoutNode,ConditionalNode,SelectionListNode,ModalNode, andContainerNodeall properly implement lifecycle propagationTerminaApplicationnow properly disposes cached pages viaIDisposableimplementation- Fixes race conditions and ensures proper resource cleanup
- Implemented Active/Inactive State Pattern for layout nodes to prevent
Improvements:
-
Add TERMINA002 analyzer and refactor MVVM architecture (#68)
- New Roslyn analyzer (TERMINA002) detects layout nodes incorrectly stored as fields/properties in ViewModels
- Refactored MVVM pattern: ViewModel owns Input (public) for business logic, Page owns Focus for interactive control
- ViewModels now handle keyboard input directly in
OnActivated() - Pages can access
ViewModel.Inputwhen routing to interactive layout nodes - Updated documentation to reflect clearer separation of concerns
- Reduces ceremony while maintaining clean MVVM architecture
-
Documentation improvements (#66)
- Added quick install section to docs homepage with NuGet badges and installation commands
- Improved documentation discoverability for new users
- Fixed docs deployment workflow trigger
0.2.1 December 16th 2025
Improvements:
- Diff-based rendering system ([#61](https://github.com/Aaronontheweb/...
Termina 0.4.0
0.4.0 December 17th 2025
Breaking Changes:
- VerticalLayout and HorizontalLayout now default to Auto() sizing (#97)
- Previously, these layouts defaulted to Fill(), which caused nested layouts to compete with siblings for space
- New Auto() default means nested layouts size to their content by default
- Fill() is now only needed for children that should claim remaining space within a container
- Root layouts always fill terminal bounds regardless of constraints
- StackLayout retains Fill() as its default since overlays should fill
- Fixes #95
New Features:
-
Rich content support for SelectionListNode (#96)
- New
SelectionItemContentclass for multi-line, styled selection items - Support for
ITextSegment(static and animated) in selection item content - "Other" option with inline text input for custom user responses
- Multi-line items with per-line styling and animated segments (spinners, etc.)
- Proper coordinate translation via sub-context rendering
- New
-
Platform-native console abstraction for event-driven input (#90)
- Replaced polling-based input with platform-native event-driven input on Windows
- Windows console enables VT100/ANSI support via
ENABLE_VIRTUAL_TERMINAL_PROCESSING - Event-driven input via
ReadConsoleInputWeliminates polling latency - Window resize events via
WINDOW_BUFFER_SIZE_EVENT - ~1000x rendering performance improvement on Windows (22-60ms → 0.02-0.08ms per frame)
- Cached console dimensions to avoid repeated P/Invoke calls
- Fallback console for non-Windows platforms with 1ms polling delay
- Closes #78, #79, #81
-
Formalized diagnostic tracing system (#84)
- Lightweight, zero-cost-when-disabled tracing system for debugging TUI applications
- Custom abstraction over Microsoft.Extensions.Logging (no direct dependency required)
- Deferred string formatting via
TraceEventstruct with template and args - Lock-free file output using Channel with single reader pattern
- Category-based filtering (Focus, Layout, Input, Page, Render, etc.)
- Level-based filtering (Trace, Debug, Info, Warning, Error)
- Optional MEL integration via
LoggerTraceListeneradapter - DI extension methods for easy configuration
- Trace logs written to %TEMP%/termina-logs/ with timestamped filenames
- Addresses #72
0.3.0 December 17th 2025
New Features:
- Inline animated text segments with tracked segment support (#71)
- Opt-in tracked segments for
StreamingTextNodeenabling inline animations (spinners, timers, etc.) - Caller-provided
SegmentIdsystem (like HTML div IDs) for tracking and manipulating segments - New interfaces:
ITextSegment,IAnimatedTextSegment,ICompositeTextSegment SpinnerSegmentcomponent with 6 animation styles: Dots, Line, Arrow, Bounce, Box, CircleStaticTextSegmentfor trackable static text- Methods:
AppendTracked(id, segment),Replace(id, segment, keepTracked),Remove(id) - Interface-based message protocol with
IChatMessagefor clean chat operations - Enables any inline animated element (timers, progress bars, blinks, highlighters) with minimal overhead
- Opt-in tracked segments for
Bug Fixes:
-
Fix modal text input not accepting keystrokes (#70, #74)
- Critical fix where
TextInputNodein modal dialogs would be immediately disposed after being focused - Fixed
ReactiveLayoutNodelifecycle to callOnDeactivate()instead ofDispose()when switching children - Fixed modal focus propagation -
ModalNodenow forwardsOnFocused()andOnBlurred()to content - Fixed
ReactiveLayoutNodeto callOnActivate()on new children when they are dynamically swapped in - Fixed render loop invalidation to properly propagate through container hierarchy
- Users can now properly type in modal dialogs without
ObjectDisposedException
- Critical fix where
-
Fix NavigationBehavior.PreserveState layout disposal issue (#67, #69)
- Implemented Active/Inactive State Pattern for layout nodes to prevent
ObjectDisposedExceptionwhen navigating - Added
IActivatableNodeinterface definingOnActivate/OnDeactivatelifecycle methods - Layout nodes now pause/resume instead of dispose/recreate on navigation with PreserveState behavior
ReactivePagenow builds layout once and preserves it across navigationsTextInputNode,SpinnerNode,ReactiveLayoutNode,ConditionalNode,SelectionListNode,ModalNode, andContainerNodeall properly implement lifecycle propagationTerminaApplicationnow properly disposes cached pages viaIDisposableimplementation- Fixes race conditions and ensures proper resource cleanup
- Implemented Active/Inactive State Pattern for layout nodes to prevent
Improvements:
-
Add TERMINA002 analyzer and refactor MVVM architecture (#68)
- New Roslyn analyzer (TERMINA002) detects layout nodes incorrectly stored as fields/properties in ViewModels
- Refactored MVVM pattern: ViewModel owns Input (public) for business logic, Page owns Focus for interactive control
- ViewModels now handle keyboard input directly in
OnActivated() - Pages can access
ViewModel.Inputwhen routing to interactive layout nodes - Updated documentation to reflect clearer separation of concerns
- Reduces ceremony while maintaining clean MVVM architecture
-
Documentation improvements (#66)
- Added quick install section to docs homepage with NuGet badges and installation commands
- Improved documentation discoverability for new users
- Fixed docs deployment workflow trigger
0.2.1 December 16th 2025
Improvements:
- Diff-based rendering system (#61)
- Implemented double-buffering terminal wrapper that eliminates screen flickering
- Only outputs changed cells on flush instead of clearing entire screen
- New
DiffingTerminalwrapper withFrameBufferfor efficient cell-level diffing - Uses same proven pattern as ncurses and termbox for flicker-free rendering
TerminaApplicationautomatically wraps terminals withDiffingTerminal- Added
ForceFullRefresh()for complete redraw when needed (resize/corruption)
Bug Fixes:
- Fix terminal state cleanup on application exit (#62)
- Properly restore terminal when Termina application exits
- Disable mouse tracking if enabled
- Reset colors and text attributes
- Flush buffered ANSI commands
- Prevents visual artifacts and inconsistent terminal state after exit
- Fixes #44
0.2.0 December 16th 2025
Breaking Changes:
- Pure reactive architecture (#50)
- All .NET events migrated to
IObservable<T>for consistency with System.Reactive IInvalidatingNode.Invalidated:event Action?→IObservable<Unit>TextInputNode:Submitted,TextChanged,Invalidatednow use observables- Other components (
SpinnerNode,ConditionalNode,ReactiveLayoutNode,ScrollableContainerNode,StreamingTextNode) migrated to observables - Rendering layer events migrated:
OnSubmit→Submitted,OnDirty→Dirty - Migration required: Replace event subscriptions (
+=) with observable subscriptions (.Subscribe()) - Use
.DisposeWith()for automatic subscription cleanup in ViewModels
- All .NET events migrated to
New Features:
- Focus management system (#51)
- Stack-based focus management for interactive components
IFocusableinterface for components that can receive keyboard focusIFocusManagerwith priority-based focus routingTerminaApplicationnow routes keyboard input through focus managerReactiveViewModelexposesFocusproperty for managing focus state
- ModalNode component (#51)
- Overlay component for modal dialogs and selection prompts
- Configurable backdrop styles: Transparent, Dim, Solid
- Positioning options: Center, Top, Bottom
- Escape key dismissal support
- Integrates with focus management system
- Created via
Layouts.Modal()factory method
- SelectionListNode component (#51)
- Keyboard-navigable selection lists with single/multi-select modes
- Number key shortcuts (1-9) for quick selection
- Home/End navigation and automatic scrolling
- Optional "Other" option for custom text input
- Typed items support with
SelectionListNode<T> - Created via
Layouts.SelectionList()factory methods - Exposes
SelectionConfirmedandSelectionCancelledobservables
- DeferredNode component (#51)
- Non-owning node delegation pattern for reactive layouts
- Prevents
ObjectDisposedExceptionwhen conditionally showing/hiding nodes - Useful for modal dialogs that shouldn't be disposed when hidden
- Created via
Layouts.Deferred()factory method
- Inline styled text support (#48)
- Structured...
Termina 0.3.0
0.3.0 December 17th 2025
New Features:
- Inline animated text segments with tracked segment support (#71)
- Opt-in tracked segments for
StreamingTextNodeenabling inline animations (spinners, timers, etc.) - Caller-provided
SegmentIdsystem (like HTML div IDs) for tracking and manipulating segments - New interfaces:
ITextSegment,IAnimatedTextSegment,ICompositeTextSegment SpinnerSegmentcomponent with 6 animation styles: Dots, Line, Arrow, Bounce, Box, CircleStaticTextSegmentfor trackable static text- Methods:
AppendTracked(id, segment),Replace(id, segment, keepTracked),Remove(id) - Interface-based message protocol with
IChatMessagefor clean chat operations - Enables any inline animated element (timers, progress bars, blinks, highlighters) with minimal overhead
- Opt-in tracked segments for
Bug Fixes:
-
Fix modal text input not accepting keystrokes (#70, #74)
- Critical fix where
TextInputNodein modal dialogs would be immediately disposed after being focused - Fixed
ReactiveLayoutNodelifecycle to callOnDeactivate()instead ofDispose()when switching children - Fixed modal focus propagation -
ModalNodenow forwardsOnFocused()andOnBlurred()to content - Fixed
ReactiveLayoutNodeto callOnActivate()on new children when they are dynamically swapped in - Fixed render loop invalidation to properly propagate through container hierarchy
- Users can now properly type in modal dialogs without
ObjectDisposedException
- Critical fix where
-
Fix NavigationBehavior.PreserveState layout disposal issue (#67, #69)
- Implemented Active/Inactive State Pattern for layout nodes to prevent
ObjectDisposedExceptionwhen navigating - Added
IActivatableNodeinterface definingOnActivate/OnDeactivatelifecycle methods - Layout nodes now pause/resume instead of dispose/recreate on navigation with PreserveState behavior
ReactivePagenow builds layout once and preserves it across navigationsTextInputNode,SpinnerNode,ReactiveLayoutNode,ConditionalNode,SelectionListNode,ModalNode, andContainerNodeall properly implement lifecycle propagationTerminaApplicationnow properly disposes cached pages viaIDisposableimplementation- Fixes race conditions and ensures proper resource cleanup
- Implemented Active/Inactive State Pattern for layout nodes to prevent
Improvements:
-
Add TERMINA002 analyzer and refactor MVVM architecture (#68)
- New Roslyn analyzer (TERMINA002) detects layout nodes incorrectly stored as fields/properties in ViewModels
- Refactored MVVM pattern: ViewModel owns Input (public) for business logic, Page owns Focus for interactive control
- ViewModels now handle keyboard input directly in
OnActivated() - Pages can access
ViewModel.Inputwhen routing to interactive layout nodes - Updated documentation to reflect clearer separation of concerns
- Reduces ceremony while maintaining clean MVVM architecture
-
Documentation improvements (#66)
- Added quick install section to docs homepage with NuGet badges and installation commands
- Improved documentation discoverability for new users
- Fixed docs deployment workflow trigger
Termina 0.2.1
0.2.1 December 16th 2025
Improvements:
- Diff-based rendering system (#61)
- Implemented double-buffering terminal wrapper that eliminates screen flickering
- Only outputs changed cells on flush instead of clearing entire screen
- New
DiffingTerminalwrapper withFrameBufferfor efficient cell-level diffing - Uses same proven pattern as ncurses and termbox for flicker-free rendering
TerminaApplicationautomatically wraps terminals withDiffingTerminal- Added
ForceFullRefresh()for complete redraw when needed (resize/corruption)
Bug Fixes:
- Fix terminal state cleanup on application exit (#62)
- Properly restore terminal when Termina application exits
- Disable mouse tracking if enabled
- Reset colors and text attributes
- Flush buffered ANSI commands
- Prevents visual artifacts and inconsistent terminal state after exit
- Fixes #44
0.2.0 December 16th 2025
Breaking Changes:
- Pure reactive architecture (#50)
- All .NET events migrated to
IObservable<T>for consistency with System.Reactive IInvalidatingNode.Invalidated:event Action?→IObservable<Unit>TextInputNode:Submitted,TextChanged,Invalidatednow use observables- Other components (
SpinnerNode,ConditionalNode,ReactiveLayoutNode,ScrollableContainerNode,StreamingTextNode) migrated to observables - Rendering layer events migrated:
OnSubmit→Submitted,OnDirty→Dirty - Migration required: Replace event subscriptions (
+=) with observable subscriptions (.Subscribe()) - Use
.DisposeWith()for automatic subscription cleanup in ViewModels
- All .NET events migrated to
New Features:
- Focus management system (#51)
- Stack-based focus management for interactive components
IFocusableinterface for components that can receive keyboard focusIFocusManagerwith priority-based focus routingTerminaApplicationnow routes keyboard input through focus managerReactiveViewModelexposesFocusproperty for managing focus state
- ModalNode component (#51)
- Overlay component for modal dialogs and selection prompts
- Configurable backdrop styles: Transparent, Dim, Solid
- Positioning options: Center, Top, Bottom
- Escape key dismissal support
- Integrates with focus management system
- Created via
Layouts.Modal()factory method
- SelectionListNode component (#51)
- Keyboard-navigable selection lists with single/multi-select modes
- Number key shortcuts (1-9) for quick selection
- Home/End navigation and automatic scrolling
- Optional "Other" option for custom text input
- Typed items support with
SelectionListNode<T> - Created via
Layouts.SelectionList()factory methods - Exposes
SelectionConfirmedandSelectionCancelledobservables
- DeferredNode component (#51)
- Non-owning node delegation pattern for reactive layouts
- Prevents
ObjectDisposedExceptionwhen conditionally showing/hiding nodes - Useful for modal dialogs that shouldn't be disposed when hidden
- Created via
Layouts.Deferred()factory method
- Inline styled text support (#48)
- Structured API for colored and decorated text in
StreamingTextNode TextDecorationflags: Bold, Dim, Italic, Underline, StrikethroughTextStylerecord combining foreground, background, and decorationsStyledSegmentandStyledLinefor composing styled textStyledWordWrapperpreserves styles across word wrap boundaries- New styled
Append/AppendLineoverloads onStreamingTextNode - Avoids escaping issues with LLM output and user content
- Structured API for colored and decorated text in
Bug Fixes:
- Fix auto-disposal of reactive fields (#49)
- Source generator now creates
DisposeReactiveFields()method for classes with[Reactive]fields - Auto-generates
Dispose()override forReactiveViewModelsubclasses - Added TERMINA001 compiler error when custom
Dispose()doesn't callDisposeReactiveFields() - Prevents
BehaviorSubjectbacking field leaks
- Source generator now creates
Improvements:
- Updated documentation with new components (ModalNode, SelectionListNode, DeferredNode)
- Added
WithChild()method toStackLayoutfor fluent API consistency TextInputNodenow implementsIFocusablefor modal integration- Enhanced Todo demo showcasing modal dialogs and two-step input flows
- 48 new unit tests covering focus management, modals, and selection lists
0.1.0 December 15th 2025
First stable release of Termina - a reactive terminal UI (TUI) framework for .NET.
Major Changes:
This release represents a complete architectural redesign from the beta, removing the Spectre.Console dependency and introducing a custom ANSI terminal rendering system with a declarative layout API.
Breaking Changes:
- Complete removal of Spectre.Console dependency (#33)
- Replaced with custom ANSI terminal rendering system for direct terminal control
- New tree-based declarative layout API replaces component-based approach
- Surgical region-based updates for better performance
- New layout components:
TextNode,PanelNode,TextInputNode,ScrollableContainerNode,StreamingTextNode,SpinnerNode - New layout containers:
Layouts.Vertical()andLayouts.Horizontal()with fluent API - Size constraint system:
Fixed,Fill,Auto,Percent - Pages now use
BuildLayout()returningILayoutNodeinstead of render-based approach - Migration required: All beta applications will need to be rewritten using the new declarative layout API
New Features:
- Live documentation website (#40)
- Comprehensive VitePress documentation now available at https://aaronstannard.com/Termina/
- Includes getting started guides, tutorials, component reference, and advanced topics
- Code examples synced with actual source files
- Automated deployment on releases
- Word wrapping support (#38)
TextNodeautomatically wraps text to multiple lines when exceeding available width- Configurable via
WordWrapproperty andNoWrap()fluent method
- Automatic terminal resize detection (#37)
- UI automatically adjusts when terminal window is resized
- Cross-platform polling approach works on all platforms
- Streaming text components (#24)
- Two-tier buffer architecture with Persisted and Windowed modes
StreamingTextNodefor chat interfaces, logs, and LLM output- Word wrapping support for streaming content
- Includes streaming chat demo with Akka.NET
Bug Fixes:
- Fix
TextInputNodetimer disposal race condition preventing crashes during shutdown (#34) - Fix
PreserveStatesubscription leak by auto-disposing subscriptions inReactiveViewModel(#35) - Fix reactive layout disposal bug (#39)
Improvements:
- XML documentation now generated for all public APIs
- Enhanced demos moved to dedicated
demos/folder - Better AOT/trimming support with analyzer packaging improvements
0.1.0-beta1 December 11th 2025
Initial release of Termina - a reactive terminal UI (TUI) framework for .NET.
Features:
- Reactive MVVM architecture with source-generated properties
- ASP.NET Core-style routing with parameterized routes and type constraints
- Two-tier event architecture (pages and navigation)
- Virtualizable input support for large datasets
- Built on Spectre.Console for rich terminal rendering
- Full AOT/trimming compatibility
Termina 0.2.0
0.2.0 December 16th 2025
Breaking Changes:
- Pure reactive architecture (#50)
- All .NET events migrated to
IObservable<T>for consistency with System.Reactive IInvalidatingNode.Invalidated:event Action?→IObservable<Unit>TextInputNode:Submitted,TextChanged,Invalidatednow use observables- Other components (
SpinnerNode,ConditionalNode,ReactiveLayoutNode,ScrollableContainerNode,StreamingTextNode) migrated to observables - Rendering layer events migrated:
OnSubmit→Submitted,OnDirty→Dirty - Migration required: Replace event subscriptions (
+=) with observable subscriptions (.Subscribe()) - Use
.DisposeWith()for automatic subscription cleanup in ViewModels
- All .NET events migrated to
New Features:
- Focus management system (#51)
- Stack-based focus management for interactive components
IFocusableinterface for components that can receive keyboard focusIFocusManagerwith priority-based focus routingTerminaApplicationnow routes keyboard input through focus managerReactiveViewModelexposesFocusproperty for managing focus state
- ModalNode component (#51)
- Overlay component for modal dialogs and selection prompts
- Configurable backdrop styles: Transparent, Dim, Solid
- Positioning options: Center, Top, Bottom
- Escape key dismissal support
- Integrates with focus management system
- Created via
Layouts.Modal()factory method
- SelectionListNode component (#51)
- Keyboard-navigable selection lists with single/multi-select modes
- Number key shortcuts (1-9) for quick selection
- Home/End navigation and automatic scrolling
- Optional "Other" option for custom text input
- Typed items support with
SelectionListNode<T> - Created via
Layouts.SelectionList()factory methods - Exposes
SelectionConfirmedandSelectionCancelledobservables
- DeferredNode component (#51)
- Non-owning node delegation pattern for reactive layouts
- Prevents
ObjectDisposedExceptionwhen conditionally showing/hiding nodes - Useful for modal dialogs that shouldn't be disposed when hidden
- Created via
Layouts.Deferred()factory method
- Inline styled text support (#48)
- Structured API for colored and decorated text in
StreamingTextNode TextDecorationflags: Bold, Dim, Italic, Underline, StrikethroughTextStylerecord combining foreground, background, and decorationsStyledSegmentandStyledLinefor composing styled textStyledWordWrapperpreserves styles across word wrap boundaries- New styled
Append/AppendLineoverloads onStreamingTextNode - Avoids escaping issues with LLM output and user content
- Structured API for colored and decorated text in
Bug Fixes:
- Fix auto-disposal of reactive fields (#49)
- Source generator now creates
DisposeReactiveFields()method for classes with[Reactive]fields - Auto-generates
Dispose()override forReactiveViewModelsubclasses - Added TERMINA001 compiler error when custom
Dispose()doesn't callDisposeReactiveFields() - Prevents
BehaviorSubjectbacking field leaks
- Source generator now creates
Improvements:
- Updated documentation with new components (ModalNode, SelectionListNode, DeferredNode)
- Added
WithChild()method toStackLayoutfor fluent API consistency TextInputNodenow implementsIFocusablefor modal integration- Enhanced Todo demo showcasing modal dialogs and two-step input flows
- 48 new unit tests covering focus management, modals, and selection lists
Termina 0.1.0
0.1.0 December 15th 2025
First stable release of Termina - a reactive terminal UI (TUI) framework for .NET.
Major Changes:
This release represents a complete architectural redesign from the beta, removing the Spectre.Console dependency and introducing a custom ANSI terminal rendering system with a declarative layout API.
Breaking Changes:
- Complete removal of Spectre.Console dependency (#33)
- Replaced with custom ANSI terminal rendering system for direct terminal control
- New tree-based declarative layout API replaces component-based approach
- Surgical region-based updates for better performance
- New layout components:
TextNode,PanelNode,TextInputNode,ScrollableContainerNode,StreamingTextNode,SpinnerNode - New layout containers:
Layouts.Vertical()andLayouts.Horizontal()with fluent API - Size constraint system:
Fixed,Fill,Auto,Percent - Pages now use
BuildLayout()returningILayoutNodeinstead of render-based approach - Migration required: All beta applications will need to be rewritten using the new declarative layout API
New Features:
- Live documentation website (#40)
- Comprehensive VitePress documentation now available at https://aaronstannard.com/Termina/
- Includes getting started guides, tutorials, component reference, and advanced topics
- Code examples synced with actual source files
- Automated deployment on releases
- Word wrapping support (#38)
TextNodeautomatically wraps text to multiple lines when exceeding available width- Configurable via
WordWrapproperty andNoWrap()fluent method
- Automatic terminal resize detection (#37)
- UI automatically adjusts when terminal window is resized
- Cross-platform polling approach works on all platforms
- Streaming text components (#24)
- Two-tier buffer architecture with Persisted and Windowed modes
StreamingTextNodefor chat interfaces, logs, and LLM output- Word wrapping support for streaming content
- Includes streaming chat demo with Akka.NET
Bug Fixes:
- Fix
TextInputNodetimer disposal race condition preventing crashes during shutdown (#34) - Fix
PreserveStatesubscription leak by auto-disposing subscriptions inReactiveViewModel(#35) - Fix reactive layout disposal bug (#39)
Improvements:
- XML documentation now generated for all public APIs
- Enhanced demos moved to dedicated
demos/folder - Better AOT/trimming support with analyzer packaging improvements
0.1.0-beta1 December 11th 2025
Initial release of Termina - a reactive terminal UI (TUI) framework for .NET.
Features:
- Reactive MVVM architecture with source-generated properties
- ASP.NET Core-style routing with parameterized routes and type constraints
- Two-tier event architecture (pages and navigation)
- Virtualizable input support for large datasets
- Built on Spectre.Console for rich terminal rendering
- Full AOT/trimming compatibility
Termina 0.1.0-beta1
0.1.0-beta1 December 11th 2025
Initial release of Termina - a reactive terminal UI (TUI) framework for .NET.
Features:
- Reactive MVVM architecture with source-generated properties
- ASP.NET Core-style routing with parameterized routes and type constraints
- Two-tier event architecture (pages and navigation)
- Virtualizable input support for large datasets
- Built on Spectre.Console for rich terminal rendering
- Full AOT/trimming compatibility