Skip to content

Conversation

@Aaronontheweb
Copy link
Owner

Summary

Implements capture-phase input handling where pages can intercept keyboard input before focused components receive it. This enables reliable navigation key handling (Escape, Tab) in gallery demos and other complex pages.

  • Add PageKeyBindings class for registering page-level key handlers
  • Add HandlePageInput method to IBindablePage interface
  • Modify TerminaApplication.ProcessEvent() to call page handler first (capture phase) before routing to focused components (bubble phase)
  • Update ReactivePage to expose KeyBindings property
  • Update all gallery demo pages to use new KeyBindings pattern for navigation
  • Add comprehensive unit and integration tests for page-level input handling

Test plan

  • All 734 existing tests pass
  • New unit tests for PageKeyBindings class
  • Integration tests verifying capture-phase intercepts before focused components
  • Manual testing of gallery demo navigation (Escape, Tab, Q keys)

Closes #104

Implement capture-phase input handling where pages intercept keys before
focused components, enabling reliable navigation key handling (Escape, Tab).

- Add PageKeyBindings class for registering page-level key handlers
- Add HandlePageInput method to IBindablePage interface
- Modify TerminaApplication.ProcessEvent() to call page handler first
- Update ReactivePage to expose KeyBindings property
- Update all gallery demo pages to use new KeyBindings pattern
- Add comprehensive tests for page-level input handling

Closes #104
Give Pages direct access to Navigate(), NavigateWithParams(), and Shutdown()
methods instead of requiring wrapper methods on ViewModels.

Framework changes:
- Add WireUpNavigation() to IBindablePage interface
- Add protected Navigate/NavigateWithParams/Shutdown methods to ReactivePage
- Update TerminaApplication to wire up navigation to pages

This is a cleaner framework design where:
- Pages use Navigate() for input-driven navigation (Escape key, etc.)
- ViewModels use Navigate() for business-logic-driven navigation

Documentation updates:
- Update input-handling.md with correct Page.Navigate() usage
- Update architecture.md with two-phase input routing model
- Update concepts index with new data flow diagram
ReactiveLayoutNode now properly subscribes to its child's Invalidated
observable and propagates those events upward. This fixes the issue where
animated nodes (like SpinnerNode) nested inside reactive layouts would
not trigger redraws because their invalidation events were lost at the
ReactiveLayoutNode boundary.

Changes:
- Added _childInvalidationSubscription field to track child subscriptions
- Added SubscribeToChildInvalidation helper method
- Subscribe to child invalidation when new child is set from observable
- Re-subscribe on OnActivate to handle reactivation after navigation
- Properly dispose child invalidation subscription in Dispose
- Applied same fix to both ReactiveLayoutNode and ReactiveLayoutNode<T>
Register a page-level key binding for Spacebar that updates the spinner
preview based on the currently highlighted item. This provides the same
behavior as Enter for this single-select use case, making the UX more
intuitive.
Highlight the scrollbar feature by renaming the column header and
updating the description to show visible rows configuration.
@Aaronontheweb Aaronontheweb merged commit d50182b into dev Dec 18, 2025
7 checks passed
@Aaronontheweb Aaronontheweb deleted the feature/page-level-key-bindings branch December 18, 2025 19:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Input routing architecture: Page/ViewModel should handle keys before child components

2 participants