build_tools.tui_common
Shared TUI Components - Common UI widgets and services for Textual-based TUIs.
This package provides reusable components for building Terminal User Interfaces using the Textual framework. It is designed to be shared across multiple TUI applications within the pipeworks_name_generation project.
Design Philosophy:
Decoupled: Widgets communicate via Textual Messages, not direct state access
Configurable: Validators and callbacks allow domain-specific customization
Consistent: Common styling patterns, keybindings, and interaction models
Tested: All components have comprehensive test coverage
Package Structure:
tui_common/
├── __init__.py # This file - package entry point
├── cli_utils.py # Shared CLI utilities (tab completion, file discovery)
├── controls/ # Reusable UI widgets
│ ├── sliders.py # FloatSlider - float parameter control
│ ├── spinners.py # IntSpinner - integer parameter control
│ ├── inputs.py # SeedInput, RadioOption - input widgets
│ └── browsers.py # DirectoryBrowserScreen - file browser modal
└── services/ # Backend services
└── config.py # KeybindingConfig - keybinding management
Usage Example:
from build_tools.tui_common.controls import (
FloatSlider,
IntSpinner,
SeedInput,
RadioOption,
DirectoryBrowserScreen,
)
from build_tools.tui_common.services import KeybindingConfig, load_keybindings
# In your Textual App
class MyApp(App):
def compose(self) -> ComposeResult:
yield IntSpinner("Count", value=5, min_val=1, max_val=100, id="count")
yield FloatSlider("Temperature", value=0.5, min_val=0.0, max_val=1.0, id="temp")
@on(IntSpinner.Changed)
def on_spinner_changed(self, event: IntSpinner.Changed) -> None:
self.notify(f"Spinner {event.widget_id} changed to {event.value}")
Message-Based Communication:
All widgets post Messages when their values change:
IntSpinner.Changed(value: int, widget_id: str | None)FloatSlider.Changed(value: float, widget_id: str | None)SeedInput.Changed(value: int, widget_id: str | None)RadioOption.Selected(option_name: str, widget_id: str | None)
Keybinding Patterns:
Widgets define widget-level bindings that don’t interfere with app-level navigation:
+/-orj/k: Increment/decrement valuesEnter/Space: Activate/select optionsh/j/k/l: Vim-style navigation in browsers
App-level bindings (q for quit, number keys for tabs, etc.) remain
unaffected when child widgets have focus.