Skip to content

Add focus management system, ModalNode, and SelectionListNode components#51

Merged
Aaronontheweb merged 4 commits into
devfrom
feature/focus-management-system
Dec 16, 2025
Merged

Add focus management system, ModalNode, and SelectionListNode components#51
Aaronontheweb merged 4 commits into
devfrom
feature/focus-management-system

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Owner

Summary

Implements GitHub issue #43 - Modal/Overlay component for selection prompts.

This PR adds a complete focus management system and new interactive components:

  • Focus Management System: Routes keyboard input to focused interactive components with a priority-based stack for nested modals
  • ModalNode: Overlay component with configurable backdrop (transparent, dim, solid), positioning (center, top, bottom), and Escape dismissal
  • SelectionListNode: Interactive list selection with single/multi-select modes, keyboard navigation, number keys for quick selection, and optional "Other" text input
  • DeferredNode: Non-owning wrapper that prevents ObjectDisposedException when showing/hiding components in reactive layouts
  • TextInputNode IFocusable: Text inputs now implement IFocusable for seamless modal integration

Key Features

ModalNode:

  • Configurable backdrop styles and colors
  • Border styles matching PanelNode
  • Forwards input to focusable content
  • Observable-based dismissal handling

SelectionListNode:

  • Single and multi-select modes
  • Arrow keys, Home/End, Space (toggle), Enter (confirm)
  • Number keys 1-9 for quick selection
  • "Other" option with immediate inline text input
  • Scrolling for long lists

Focus Management:

  • Focus.PushFocus(modal) / Focus.PopFocus() API
  • Priority-based input routing
  • IFocusable interface for custom interactive components

Test plan

  • All 516 existing tests pass
  • New FocusManager tests (245 lines)
  • New ModalNode tests (223 lines)
  • New SelectionListNode tests (454 lines)
  • Manual testing with TodoListPage demo
  • Verify documentation renders correctly in VitePress

Closes #43

Implement a stack-based focus management system to support modals and
interactive components that need to capture keyboard input.

New files:
- IFocusable.cs: Interface for components that can receive focus
  (CanFocus, HasFocus, FocusPriority, OnFocused/OnBlurred, HandleInput)
- IFocusManager.cs: Interface for managing focus state
  (PushFocus, PopFocus, SetFocus, ClearFocus, RouteInput)
- FocusManager.cs: Stack-based implementation using BehaviorSubject
  for reactive focus change notifications

Integration:
- TerminaApplication now routes KeyPressed events through focus manager
  before passing to ViewModel, allowing focused components to consume input
- ReactiveViewModel exposes Focus property for ViewModels to manage focus
- Updated WireUp() to pass focus manager to ViewModels

Testing:
- Added 14 comprehensive tests for FocusManager behavior
- Updated ReactiveViewModelTests to include focus manager parameter

This lays the groundwork for ModalNode and SelectionListNode components.
This implements GitHub issue #43 - Modal/Overlay component for selection prompts.

New Components:
- ModalNode: Overlay component with configurable backdrops (Transparent, Dim, Solid),
  positioning (Center, Top, Bottom), borders, and Escape key dismissal
- SelectionListNode<T>: Keyboard-navigable list with single/multi-select modes,
  number key shortcuts, Home/End navigation, scrolling, and "Other" custom input

Supporting Types:
- BackdropStyle, ModalPosition, SelectionMode enums
- SelectionItem<T> for list items with IsSelected state

Factory Methods:
- Layouts.Modal() for creating modals
- Layouts.SelectionList() for creating selection lists (typed and string variants)

Demo Integration:
- Updated Todo demo to use modal dialogs for adding new items
- Two-step flow: text input modal → priority selection modal
- Demonstrates modal stacking and focus management

Tests:
- 17 tests for ModalNode (focus, input handling, dismissal, observables)
- 17 tests for SelectionListNode (navigation, selection, modes, observables)

Other Changes:
- Added WithChild() method to StackLayout for fluent API consistency
- Add IFocusable implementation to TextInputNode so modals can forward
  keyboard input to text input content
- Fix SelectionListNode single mode to always select highlighted item
  on Enter, not just when nothing is selected
- Fix "Other" option to auto-start text input when navigated to or
  selected via number key, providing immediate typing without needing
  Enter first
- Render "Other" text input inline replacing the option text instead
  of on a separate line below
- Add DeferredNode to framework for rendering nodes without owning
  their lifecycle (useful for modals that should not be disposed when
  hidden)
- Update TodoListPage to use Layouts.Deferred() instead of private
  wrapper class
- Add tests for single mode Enter behavior and Other option auto-edit
- Add ModalNode documentation covering backdrop styles, positioning,
  interactive content integration, and complete usage examples
- Add SelectionListNode documentation covering single/multi-select modes,
  keyboard shortcuts, "Other" option for custom input, and typed items
- Add DeferredNode documentation explaining non-owning node delegation
  pattern for preventing ObjectDisposedException with reactive layouts
- Update components index to include all three new components
- Add sidebar navigation entries in VitePress config
@Aaronontheweb Aaronontheweb enabled auto-merge (squash) December 16, 2025 18:21
@Aaronontheweb Aaronontheweb merged commit 1a285b8 into dev Dec 16, 2025
7 checks passed
@Aaronontheweb Aaronontheweb deleted the feature/focus-management-system branch December 16, 2025 18:22
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.

Feature Request: Modal/Overlay component for selection prompts

1 participant