Repository: Textualize/textual
File: src/textual/scrollbar.py (Python)

Code before:


class ScrollTo(ScrollMessage, verbose=True):
    """Message sent when click and dragging handle."""

    __slots__ = ["x", "y", "animate"]

    def __init__(
        self,
        x: float | None = None,
        y: float | None = None,
        animate: bool = True,
    ) -> None:
        self.x = x
        self.y = y
        self.animate = animate
        super().__init__()

    def __rich_repr__(self) -> rich.repr.Result:
        yield "x", self.x, None
        yield "y", self.y, None
        yield "animate", self.animate, True


class ScrollBarRender:
    _vertical_bars: ClassVar[list[str]] = ["▁", "▂", "▃", "▄", "▅", "▆", "▇", " "]
    """Glyphs used for vertical scrollbar ends, for smoother display."""
    _horizontal_bars: ClassVar[list[str]] = ["▉", "▊", "▋", "▌", "▍", "▎", "▏", " "]
    """Glyphs used for horizontal scrollbar ends, for smoother display."""
    _blank_glyph: ClassVar[str] = " "
    """Glyph used for the main body of the scrollbar"""

    def __init__(
        self,
        virtual_size: int = 100,
        window_size: int = 0,
        position: float = 0,
        thickness: int = 1,
        vertical: bool = True,
        style: StyleType = "bright_magenta on #555555",
    ) -> None:
        self.virtual_size = virtual_size
        self.window_size = window_size
        self.position = position
        self.thickness = thickness
        self.vertical = vertical
        self.style = style

    @classmethod
    def render_bar(
        cls,

Review comment (suggestion):
If these are meant to be overridden, then they probably shouldn't be prefixed with an underscore. I might also put them in all-caps given they are constants to the class where they are defined.

It might also be worth considering changing them to a tuple and typing them as `tuple[str, str, str, str, str, str, str, str]`. A bit verbose, but it would allow the typechecker to mandate there are 8 items.

Code after:


class ScrollTo(ScrollMessage, verbose=True):
    """Message sent when click and dragging handle."""

    __slots__ = ["x", "y", "animate"]

    def __init__(
        self,
        x: float | None = None,
        y: float | None = None,
        animate: bool = True,
    ) -> None:
        self.x = x
        self.y = y
        self.animate = animate
        super().__init__()

    def __rich_repr__(self) -> rich.repr.Result:
        yield "x", self.x, None
        yield "y", self.y, None
        yield "animate", self.animate, True


class ScrollBarRender:
    VERTICAL_BARS: ClassVar[list[str]] = ["▁", "▂", "▃", "▄", "▅", "▆", "▇", " "]
    """Glyphs used for vertical scrollbar ends, for smoother display."""
    HORIZONTAL_BARS: ClassVar[list[str]] = ["▉", "▊", "▋", "▌", "▍", "▎", "▏", " "]
    """Glyphs used for horizontal scrollbar ends, for smoother display."""
    BLANK_GLYPH: ClassVar[str] = " "
    """Glyph used for the main body of the scrollbar"""

    def __init__(
        self,
        virtual_size: int = 100,
        window_size: int = 0,
        position: float = 0,
        thickness: int = 1,
        vertical: bool = True,
        style: StyleType = "bright_magenta on #555555",
    ) -> None:
        self.virtual_size = virtual_size
        self.window_size = window_size
        self.position = position
        self.thickness = thickness
        self.vertical = vertical
        self.style = style

    @classmethod
    def render_bar(
        cls,