wijjit.elements.base.ScrollableElement

class wijjit.elements.base.ScrollableElement(id=None, classes=None, tab_index=None)[source]

Abstract base class for elements that support scrolling.

This class provides a standard interface for elements that can scroll their content, such as lists, text areas, tables, and frames. It enforces implementation of scroll-related methods and provides state persistence through the callback system.

Variables:
  • scroll_state_key (str or None) – State key for persisting vertical scroll position. Defaults to “{id}:scroll” if element has an id. Can be explicitly set to override the default.

  • on_scroll (Callable[[int], None] or None) – Callback function called when vertical scroll position changes. Signature: on_scroll(position: int) -> None

  • scroll_state_key_x (str or None) – State key for persisting horizontal scroll position. Defaults to “{id}:scroll_x” if element has an id. Can be explicitly set to override the default.

  • on_scroll_x (Callable[[int], None] or None) – Callback function called when horizontal scroll position changes. Signature: on_scroll_x(position: int) -> None

Parameters:

Notes

Subclasses must implement: - scroll_position property: Return current scroll offset - can_scroll(direction): Check if scrolling is possible

Subclasses should: 1. Call self.on_scroll(position) when scroll position changes 2. The application will wire on_scroll to update state automatically

State keys follow the convention “{id}:{property}” for consistent naming across all elements. For example, an element with id=”my_list” will have: - scroll_state_key = “my_list:scroll” - scroll_state_key_x = “my_list:scroll_x”

Examples

Implement a scrollable list element:

>>> class ScrollableList(ScrollableElement):
...     def __init__(self, items) -> None:
...         super().__init__()
...         self.items = items
...         self._scroll_offset = 0
...
...     @property
...     def scroll_position(self) -> int:
...         return self._scroll_offset
...
...     def can_scroll(self, direction: int) -> bool:
...         if direction < 0:  # Up
...             return self._scroll_offset > 0
...         else:  # Down
...             return self._scroll_offset < len(self.items) - 1
...
...     def scroll_by(self, amount: int):
...         old_pos = self._scroll_offset
...         self._scroll_offset = max(0, min(self._scroll_offset + amount, len(self.items) - 1))
...         if self.on_scroll and old_pos != self._scroll_offset:
...             self.on_scroll(self._scroll_offset)
__init__(id=None, classes=None, tab_index=None)[source]

Initialize scrollable element.

Parameters:
  • id (str, optional) – Element identifier

  • classes (str or list of str or set of str, optional) – CSS class names for styling

  • tab_index (int, optional) – Tab order for focus navigation

Return type:

None

Methods

__init__([id, classes, tab_index])

Initialize scrollable element.

add_class(class_name)

Add a CSS class to this element.

apply_props(props)

Apply props from a VNode, skipping ephemeral props.

can_scroll(direction)

Check if the element can scroll in the given direction.

get_ephemeral_state()

Get ephemeral state that should survive reconciliation.

get_hardware_cursor_position()

Absolute screen cell where the hardware terminal cursor should park.

get_height_for_width(width)

Return the height this element needs when laid out at width.

get_intrinsic_size()

Get the intrinsic (preferred) size of the element.

handle_key(key)

Handle a key press.

handle_mouse(event)

Handle a mouse event.

has_class(class_name)

Check if element has a CSS class.

on_blur()

Called when element loses focus.

on_focus()

Called when element gains focus.

on_hover_enter()

Called when mouse enters element.

on_hover_exit()

Called when mouse exits element.

on_mount()

Called when element is first added to the element tree.

on_unmount()

Called when element is removed from the element tree.

on_update(changed_props)

Called when element props are updated during reconciliation.

remove_class(class_name)

Remove a CSS class from this element.

render_signature()

Hashable/comparable capture of everything render_to() reads.

render_to(ctx)

Render the element to a cell-based buffer.

restore_ephemeral_state(state)

Restore ephemeral state after reconciliation.

set_bounds(bounds)

Set the element's screen bounds.

toggle_class(class_name)

Toggle a CSS class on this element.

Attributes

captures_tab

Whether this element wants the Tab key instead of focus movement.

parent_frame

Get the parent Frame if this element is inside a scrollable frame.

scroll_position

Get the current scroll position.

scroll_state_key

Get the state key for vertical scroll position.

scroll_state_key_x

Get the state key for horizontal scroll position.

supports_dynamic_sizing

Whether this element supports dynamic sizing.

property scroll_state_key: str | None

Get the state key for vertical scroll position.

Returns the explicitly set key if provided, otherwise auto-generates from the element id using the convention “{id}:scroll”.

Returns:

State key for scroll position, or None if no id

Return type:

str or None

property scroll_state_key_x: str | None

Get the state key for horizontal scroll position.

Returns the explicitly set key if provided, otherwise auto-generates from the element id using the convention “{id}:scroll_x”.

Returns:

State key for horizontal scroll position, or None if no id

Return type:

str or None

abstract property scroll_position: int

Get the current scroll position.

Returns:

Current scroll offset (0-based)

Return type:

int

abstractmethod can_scroll(direction)[source]

Check if the element can scroll in the given direction.

Parameters:

direction (int) – Scroll direction: negative for up/left, positive for down/right

Returns:

True if scrolling in the given direction is possible

Return type:

bool