Skip to content

Modifiers

Functional-style modifiers to apply styling, layout, and event handling to widgets.

modifiers

focusable

focusable(enabled: bool = True, on_focus_change: Optional[FocusChangeCallback] = None, on_key: Optional[Callable[[str, int], bool]] = None) -> FocusableModifier

Mark the widget as focusable.

Parameters:

Name Type Description Default
enabled bool

Whether the widget is focusable.

True
on_focus_change Optional[FocusChangeCallback]

Callback invoked when focus state changes.

None
on_key Optional[Callable[[str, int], bool]]

Callback invoked when a key event occurs while focused. Return True to stop propagation (bubbling).

None
Source code in src/nuiitivet/modifiers/focus.py
def focusable(
    enabled: bool = True,
    on_focus_change: Optional[FocusChangeCallback] = None,
    on_key: Optional[Callable[[str, int], bool]] = None,
) -> FocusableModifier:
    """
    Mark the widget as focusable.

    Args:
        enabled: Whether the widget is focusable.
        on_focus_change: Callback invoked when focus state changes.
        on_key: Callback invoked when a key event occurs while focused.
                Return True to stop propagation (bubbling).
    """
    return FocusableModifier(enabled, on_focus_change, on_key)

modeless

modeless(content: Widget, *, is_open: Optional['Observable[bool]'] = None, alignment: AlignmentLike = 'bottom-left', anchor: AlignmentLike = 'top-left', offset: Tuple[float, float] = (0.0, 0.0), transition_spec: Optional['TransitionSpec'] = None) -> PopupModifier

Return a modeless overlay modifier anchored to the modified widget.

The overlay is rendered above the widget tree via :meth:Overlay.show_modeless, so it avoids clipping and sits at the top of the Z-order.

Parameters:

Name Type Description Default
content Widget

Widget to display as the popup overlay.

required
is_open Optional['Observable[bool]']

Observable[bool] to control open/close state. When None, an internal observable is created and exposed via :attr:PopupBox.is_open. Callers are responsible for toggling it.

None
alignment AlignmentLike

Reference point on the anchor widget (default "bottom-left").

'bottom-left'
anchor AlignmentLike

Reference point on the content widget to align to (default "top-left").

'top-left'
offset Tuple[float, float]

Additional (dx, dy) offset in screen pixels.

(0.0, 0.0)
transition_spec Optional['TransitionSpec']

Passed directly to :meth:Overlay.show_modeless for enter/exit animation.

None

Returns:

Name Type Description
A PopupModifier

class:PopupModifier suitable for :meth:Widget.modifier.

Example::

# External state control (recommended)
is_open: Observable[bool] = Observable(False)
icon_button.modifier(modeless(Menu(...), is_open=is_open))

# Explicit positioning with animation
icon_button.modifier(
    modeless(
        Menu(...),
        alignment="bottom-left",
        anchor="top-left",
        offset=(0.0, 4.0),
        transition_spec=MaterialTransitions.menu(),
    )
)
Source code in src/nuiitivet/modifiers/popup.py
def modeless(
    content: Widget,
    *,
    is_open: Optional["Observable[bool]"] = None,
    alignment: AlignmentLike = "bottom-left",
    anchor: AlignmentLike = "top-left",
    offset: Tuple[float, float] = (0.0, 0.0),
    transition_spec: Optional["TransitionSpec"] = None,
) -> PopupModifier:
    """Return a modeless overlay modifier anchored to the modified widget.

    The overlay is rendered above the widget tree via :meth:`Overlay.show_modeless`, so
    it avoids clipping and sits at the top of the Z-order.

    Args:
        content: Widget to display as the popup overlay.
        is_open: ``Observable[bool]`` to control open/close state.
            When ``None``, an internal observable is created and exposed via
            :attr:`PopupBox.is_open`. Callers are responsible for toggling it.
        alignment: Reference point on the **anchor widget** (default
            ``"bottom-left"``).
        anchor: Reference point on the **content widget** to align to (default
            ``"top-left"``).
        offset: Additional ``(dx, dy)`` offset in screen pixels.
        transition_spec: Passed directly to :meth:`Overlay.show_modeless` for
            enter/exit animation.

    Returns:
        A :class:`PopupModifier` suitable for :meth:`Widget.modifier`.

    Example::

        # External state control (recommended)
        is_open: Observable[bool] = Observable(False)
        icon_button.modifier(modeless(Menu(...), is_open=is_open))

        # Explicit positioning with animation
        icon_button.modifier(
            modeless(
                Menu(...),
                alignment="bottom-left",
                anchor="top-left",
                offset=(0.0, 4.0),
                transition_spec=MaterialTransitions.menu(),
            )
        )
    """
    return PopupModifier(
        content=content,
        is_open=is_open,
        alignment=alignment,
        anchor=anchor,
        offset=offset,
        transition_spec=transition_spec,
    )

light_dismiss

light_dismiss(content: Widget, *, is_open: Optional['Observable[bool]'] = None, alignment: AlignmentLike = 'bottom-left', anchor: AlignmentLike = 'top-left', offset: Tuple[float, float] = (0.0, 0.0), transition_spec: Optional['TransitionSpec'] = None) -> PopupModifier

Return a light-dismiss overlay modifier anchored to the modified widget.

Source code in src/nuiitivet/modifiers/popup.py
def light_dismiss(
    content: Widget,
    *,
    is_open: Optional["Observable[bool]"] = None,
    alignment: AlignmentLike = "bottom-left",
    anchor: AlignmentLike = "top-left",
    offset: Tuple[float, float] = (0.0, 0.0),
    transition_spec: Optional["TransitionSpec"] = None,
) -> PopupModifier:
    """Return a light-dismiss overlay modifier anchored to the modified widget."""
    return PopupModifier(
        content=content,
        is_open=is_open,
        alignment=alignment,
        anchor=anchor,
        offset=offset,
        transition_spec=transition_spec,
        light_dismiss=True,
    )

opacity

opacity(value: OpacityLike) -> TransformModifier

Return a modifier that applies opacity to a widget during paint.

Parameters:

Name Type Description Default
value OpacityLike

Opacity value between 0.0 (transparent) and 1.0 (opaque), or an observable providing opacity.

required
Note

Opacity is paint-only. Layout and hit-testing remain unchanged.

Source code in src/nuiitivet/modifiers/transform.py
def opacity(value: OpacityLike) -> TransformModifier:
    """Return a modifier that applies opacity to a widget during paint.

    Args:
        value: Opacity value between 0.0 (transparent) and 1.0 (opaque),
            or an observable providing opacity.

    Note:
        Opacity is paint-only. Layout and hit-testing remain unchanged.
    """
    return TransformModifier(opacity=value)

rotate

rotate(angle: AngleLike, origin: OriginLike = 'center') -> TransformModifier

Return a modifier that rotates a widget during paint.

Parameters:

Name Type Description Default
angle AngleLike

Rotation angle in degrees, or an observable providing degrees.

required
origin OriginLike

Rotation origin. Supported: "center", "top_left", "top_right", "bottom_left", "bottom_right", or a (x, y) tuple in local coords.

'center'
Note

Rotation is paint-only. Layout and hit-testing remain untransformed.

Source code in src/nuiitivet/modifiers/transform.py
def rotate(angle: AngleLike, origin: OriginLike = "center") -> TransformModifier:
    """Return a modifier that rotates a widget during paint.

    Args:
        angle: Rotation angle in degrees, or an observable providing degrees.
        origin: Rotation origin. Supported: "center", "top_left", "top_right",
            "bottom_left", "bottom_right", or a (x, y) tuple in local coords.

    Note:
        Rotation is paint-only. Layout and hit-testing remain untransformed.
    """
    return TransformModifier(rotation=angle, transform_origin=origin)

scale

scale(factor: ScaleLike, origin: OriginLike = 'center') -> TransformModifier

Return a modifier that scales a widget during paint.

Parameters:

Name Type Description Default
factor ScaleLike

Scale factor (uniform) or (sx, sy) tuple, or an observable.

required
origin OriginLike

Scale origin. Supported: "center", "top_left", "top_right", "bottom_left", "bottom_right", or a (x, y) tuple in local coords.

'center'
Note

Scale is paint-only. Layout and hit-testing remain untransformed.

Source code in src/nuiitivet/modifiers/transform.py
def scale(factor: ScaleLike, origin: OriginLike = "center") -> TransformModifier:
    """Return a modifier that scales a widget during paint.

    Args:
        factor: Scale factor (uniform) or (sx, sy) tuple, or an observable.
        origin: Scale origin. Supported: "center", "top_left", "top_right",
            "bottom_left", "bottom_right", or a (x, y) tuple in local coords.

    Note:
        Scale is paint-only. Layout and hit-testing remain untransformed.
    """
    return TransformModifier(scale=factor, transform_origin=origin)

translate

translate(offset: TranslateLike) -> TransformModifier

Return a modifier that translates a widget during paint.

Parameters:

Name Type Description Default
offset TranslateLike

Translation offset as (dx, dy) tuple, or an observable.

required
Note

Translation is paint-only. Layout and hit-testing remain untransformed.

Source code in src/nuiitivet/modifiers/transform.py
def translate(offset: TranslateLike) -> TransformModifier:
    """Return a modifier that translates a widget during paint.

    Args:
        offset: Translation offset as (dx, dy) tuple, or an observable.

    Note:
        Translation is paint-only. Layout and hit-testing remain untransformed.
    """
    return TransformModifier(translation=offset)