build_tools.tui_common.controls.spinners
Integer spinner control widget.
This module provides the IntSpinner widget for integer parameter control with keyboard support and optional dynamic suffix.
Features:
Keyboard navigation:
+/-orj/kor arrow keys to adjustConfigurable step size and min/max range
Optional suffix function for dynamic labels (e.g., “5 items”, “10 chars”)
Posts
Changedmessage when value updatesFocusable with visual feedback
Example Usage:
from build_tools.tui_common.controls import IntSpinner
from textual import on
class MyApp(App):
def compose(self) -> ComposeResult:
# Simple spinner with static label
yield IntSpinner(
label="Count",
value=5,
min_val=1,
max_val=100,
id="count-spinner",
)
# Spinner with dynamic suffix based on value
yield IntSpinner(
label="Walk Steps",
value=5,
min_val=0,
max_val=20,
suffix_fn=lambda v: f"-> {v + 1} syllables",
id="steps-spinner",
)
@on(IntSpinner.Changed)
def on_spinner_changed(self, event: IntSpinner.Changed) -> None:
print(f"Spinner {event.widget_id} = {event.value}")
Classes
Integer spinner widget with increment/decrement support. |
Module Contents
- class build_tools.tui_common.controls.spinners.IntSpinner(label, value, min_val, max_val, step=1, suffix_fn=None, *args, **kwargs)[source]
Bases:
textual.widgets.StaticInteger spinner widget with increment/decrement support.
A horizontal widget displaying a label, current value in brackets, and optional dynamic suffix. Users can adjust the value using keyboard shortcuts while the widget has focus.
- label_text
Display label shown before the value
- value
Current integer value (clamped to min/max range)
- min_val
Minimum allowed value
- max_val
Maximum allowed value
- step
Amount to increment/decrement per keypress
- suffix_fn
Optional callable that generates suffix text from current value
- Keybindings:
+or=orjordown: Increment value by step-or_orkorup: Decrement value by step
- Messages:
Changed: Posted when value changes, includes new value and widget ID
- CSS Classes:
.spinner-label: Label element (width: 15, right-aligned).spinner-value: Value display (width: 6, centered, highlighted on focus).spinner-suffix: Suffix text (auto width, muted color)
Initialize integer spinner.
- Parameters:
label (str) – Display label shown before the value
value (int) – Initial value (will be clamped to min/max range)
min_val (int) – Minimum allowed value
max_val (int) – Maximum allowed value
step (int) – Increment/decrement step size (default: 1)
suffix_fn (collections.abc.Callable[[int], str] | None) – Optional callback to generate suffix text from current value. Called with current value, returns string to display. Example:
lambda v: f"-> {v + 1} items"*args – Additional positional arguments passed to Static
**kwargs – Additional keyword arguments passed to Static
- BINDINGS = [('+', 'increment', 'Increment'), ('=', 'increment', 'Increment'), ('j', 'increment',...
A list of key bindings.
- class Changed(value, widget_id)[source]
Bases:
textual.message.MessageMessage posted when the spinner value changes.
- value
The new integer value after the change
- widget_id
The ID of the widget that posted this message, or None
Initialize the Changed message.
- Parameters:
- value
- widget_id
- DEFAULT_CSS = Multiline-String
Show Value
""" IntSpinner { layout: horizontal; height: 1; width: 100%; } IntSpinner .spinner-label { width: 15; text-align: right; padding-right: 1; } IntSpinner .spinner-value { width: 6; text-align: center; background: $boost; } IntSpinner:focus .spinner-value { background: $accent; text-style: bold; } IntSpinner .spinner-suffix { width: auto; padding-left: 1; color: $text-muted; } """
Default TCSS.
- label_text
- value
- min_val
- max_val
- step = 1
- suffix_fn = None
- compose()[source]
Create the spinner layout.
Layout: [Label:] [value] [suffix]
- Yields:
Label widgets for label, value display, and optional suffix
- on_mount()[source]
Configure widget after mounting.
Makes the widget focusable for keyboard navigation. Focus state is used to highlight the value display.
- action_increment()[source]
Increment value by step, clamped to max.
Only posts Changed message if value actually changed. Updates both value display and suffix if present.