Repository: Textualize/textual

Issue:
Add the ability to customise scrollbar bar segments
Currently, the characters that make up a scrollbar [are hardcoded](https://github.com/Textualize/textual/blob/e21f57529d4e70bf421acb7cb5e7d041a43e5a2f/src/textual/scrollbar.py#L101-L104). It would be nice if they could be overridden. Personally, I need to support poor fonts, so need to replace missing glyphs. But it would be neat to use braille characters for a unique style.

Thoughts on making them a classvar, so they can be monkeypatched in for now? I can do that PR if it's an OK change.


Discussion:
Thank you for your issue. Give us a little time to review it.

PS. You might want to check the [FAQ](https://textual.textualize.io/FAQ/) if you haven't done so already.

This is an automated reply, generated by [FAQtory](https://github.com/willmcgugan/faqtory)
You can patch in a new scrollbar renderable as follow:

```python
from textual.scrollbar import Scrollbar

ScrollBar.renderer = MyScrollbarRenderer
```

Have a look at how the [original](https://github.com/Textualize/textual/blob/main/src/textual/scrollbar.py#L72) is implemented. You can copy that and customize it.
For sure! I was just hoping for an easier way than duplicating the ~72 line render function. Textual is still developing pretty quickly, and I'm wary vendoring too much of its code to fix things.
@mon For what it's worth, the scrollbar renderer has been in place for well over a year, has been stable as far as I can remember, [and is part of the documented API](https://textual.textualize.io/api/scrollbar/#textual.scrollbar.ScrollBar.renderer).
Yeah, that's not going to change. Textual's API is quite stable now.
That's good to know! I guess then - would a PR changing the bar glyphs to be a classvar be rejected? I still do like the idea of a 3-line way to modify the class.
I think that would be reasonable. Happy to accept a PR.

Resolving patch:
diff --git a/src/textual/scrollbar.py b/src/textual/scrollbar.py
--- a/src/textual/scrollbar.py
+++ b/src/textual/scrollbar.py
@@ -70,6 +70,13 @@ def __rich_repr__(self) -> rich.repr.Result:
 
 
 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,
@@ -99,9 +106,9 @@ def render_bar(
         bar_color: Color = Color.parse("bright_magenta"),
     ) -> Segments:
         if vertical:
-            bars = ["▁", "▂", "▃", "▄", "▅", "▆", "▇", " "]
+            bars = cls.VERTICAL_BARS
         else:
-            bars = ["▉", "▊", "▋", "▌", "▍", "▎", "▏", " "]
+            bars = cls.HORIZONTAL_BARS
 
         back = back_color
         bar = bar_color
@@ -112,7 +119,7 @@ def render_bar(
 
         _Segment = Segment
         _Style = Style
-        blank = " " * width_thickness
+        blank = cls.BLANK_GLYPH * width_thickness
 
         foreground_meta = {"@mouse.down": "grab"}
         if window_size and size and virtual_size and size != virtual_size:


Test patch: