build_tools.tui_common.controls.spinners ======================================== .. py:module:: build_tools.tui_common.controls.spinners .. autoapi-nested-parse:: Integer spinner control widget. This module provides the IntSpinner widget for integer parameter control with keyboard support and optional dynamic suffix. **Features:** - Keyboard navigation: ``+``/``-`` or ``j``/``k`` or arrow keys to adjust - Configurable step size and min/max range - Optional suffix function for dynamic labels (e.g., "5 items", "10 chars") - Posts ``Changed`` message when value updates - Focusable with visual feedback **Example Usage:** .. code-block:: python 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 ------- .. autoapisummary:: build_tools.tui_common.controls.spinners.IntSpinner Module Contents --------------- .. py:class:: IntSpinner(label, value, min_val, max_val, step = 1, suffix_fn = None, *args, **kwargs) Bases: :py:obj:`textual.widgets.Static` Integer 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. .. attribute:: label_text Display label shown before the value .. attribute:: value Current integer value (clamped to min/max range) .. attribute:: min_val Minimum allowed value .. attribute:: max_val Maximum allowed value .. attribute:: step Amount to increment/decrement per keypress .. attribute:: suffix_fn Optional callable that generates suffix text from current value Keybindings: - ``+`` or ``=`` or ``j`` or ``down``: Increment value by step - ``-`` or ``_`` or ``k`` or ``up``: Decrement value by step Messages: - :class:`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. :param label: Display label shown before the value :param value: Initial value (will be clamped to min/max range) :param min_val: Minimum allowed value :param max_val: Maximum allowed value :param step: Increment/decrement step size (default: 1) :param suffix_fn: Optional callback to generate suffix text from current value. Called with current value, returns string to display. Example: ``lambda v: f"-> {v + 1} items"`` :param \*args: Additional positional arguments passed to Static :param \*\*kwargs: Additional keyword arguments passed to Static .. py:attribute:: BINDINGS :value: [('+', 'increment', 'Increment'), ('=', 'increment', 'Increment'), ('j', 'increment',... A list of key bindings. .. py:class:: Changed(value, widget_id) Bases: :py:obj:`textual.message.Message` Message posted when the spinner value changes. .. attribute:: value The new integer value after the change .. attribute:: widget_id The ID of the widget that posted this message, or None Initialize the Changed message. :param value: The new spinner value :param widget_id: ID of the spinner widget that changed .. py:attribute:: value .. py:attribute:: widget_id .. py:attribute:: DEFAULT_CSS :value: Multiline-String .. raw:: html
Show Value .. code-block:: python """ 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; } """ .. raw:: html
Default TCSS. .. py:attribute:: label_text .. py:attribute:: value .. py:attribute:: min_val .. py:attribute:: max_val .. py:attribute:: step :value: 1 .. py:attribute:: suffix_fn :value: None .. py:method:: compose() Create the spinner layout. Layout: [Label:] [value] [suffix] :Yields: Label widgets for label, value display, and optional suffix .. py:method:: on_mount() Configure widget after mounting. Makes the widget focusable for keyboard navigation. Focus state is used to highlight the value display. .. py:method:: action_increment() Increment value by step, clamped to max. Only posts Changed message if value actually changed. Updates both value display and suffix if present. .. py:method:: action_decrement() Decrement value by step, clamped to min. Only posts Changed message if value actually changed. Updates both value display and suffix if present. .. py:method:: set_value(value) Set value programmatically, clamped to range. Use this method to update the spinner value from code. Posts Changed message if value actually changed. :param value: New value (will be clamped to min/max range)