Skip to content

Commit

Permalink
Allow scrollbar size of zero (scrollable containers without scrollbar…
Browse files Browse the repository at this point in the history
…s) (#3488)

* Remove the guard code which protects against `scrollbar-size-*:0`, update error messages indicating its supported now.

* Fix scrollbar region calculation to support zero-thickness scrollbars

* Add test ensuring zero-width scrollbars dont blow up

* Updating CHANGELOG regarding zero-thickness scrollbars

* Add note to scrollbar_size.md about zero width scrollbar
  • Loading branch information
darrenburns authored Oct 10, 2023
1 parent 5e4067f commit 1a0cd77
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added `Input.clear` method https://github.com/Textualize/textual/pull/3430
- Added `TextArea.SelectionChanged` and `TextArea.Changed` messages https://github.com/Textualize/textual/pull/3442
- Added `wait_for_dismiss` parameter to `App.push_screen` https://github.com/Textualize/textual/pull/3477
- Allow scrollbar-size to be set to 0 to achieve scrollable containers with no visible scrollbars https://github.com/Textualize/textual/pull/3488

### Changed

Expand Down
5 changes: 5 additions & 0 deletions docs/styles/scrollbar_size.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ In this example we modify the size of the widget's scrollbar to be _much_ larger

In the next example we show three containers with differently sized scrollbars.

!!! tip

If you want to hide the scrollbar but still allow the container to scroll
using the mousewheel or keyboard, you can set the scrollbar size to `0`.

=== "Output"

```{.textual path="docs/examples/styles/scrollbar_size2.py"}
Expand Down
4 changes: 1 addition & 3 deletions src/textual/css/_help_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -587,9 +587,7 @@ def scrollbar_size_property_help_text(context: StylingContext) -> HelpText:
),
],
).get_by_context(context),
Bullet(
"<horizontal> and <vertical> must be positive integers, greater than zero"
),
Bullet("<horizontal> and <vertical> must be non-negative integers."),
],
)

Expand Down
8 changes: 0 additions & 8 deletions src/textual/css/_styles_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -876,11 +876,7 @@ def scrollbar_size_error(name: str, token: Token) -> None:
scrollbar_size_error(name, token2)

horizontal = int(token1.value)
if horizontal == 0:
scrollbar_size_error(name, token1)
vertical = int(token2.value)
if vertical == 0:
scrollbar_size_error(name, token2)
self.styles._rules["scrollbar_size_horizontal"] = horizontal
self.styles._rules["scrollbar_size_vertical"] = vertical
self._distribute_importance("scrollbar_size", ("horizontal", "vertical"))
Expand All @@ -895,8 +891,6 @@ def process_scrollbar_size_vertical(self, name: str, tokens: list[Token]) -> Non
if token.name != "number" or not token.value.isdigit():
self.error(name, token, scrollbar_size_single_axis_help_text(name))
value = int(token.value)
if value == 0:
self.error(name, token, scrollbar_size_single_axis_help_text(name))
self.styles._rules["scrollbar_size_vertical"] = value

def process_scrollbar_size_horizontal(self, name: str, tokens: list[Token]) -> None:
Expand All @@ -909,8 +903,6 @@ def process_scrollbar_size_horizontal(self, name: str, tokens: list[Token]) -> N
if token.name != "number" or not token.value.isdigit():
self.error(name, token, scrollbar_size_single_axis_help_text(name))
value = int(token.value)
if value == 0:
self.error(name, token, scrollbar_size_single_axis_help_text(name))
self.styles._rules["scrollbar_size_horizontal"] = value

def _process_grid_rows_or_columns(self, name: str, tokens: list[Token]) -> None:
Expand Down
10 changes: 5 additions & 5 deletions src/textual/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,7 @@ def vertical_scrollbar(self) -> ScrollBar:

@property
def horizontal_scrollbar(self) -> ScrollBar:
"""The a horizontal scrollbar.
"""The horizontal scrollbar.
Note:
This will *create* a scrollbar if one doesn't exist.
Expand Down Expand Up @@ -2701,8 +2701,8 @@ def _arrange_scrollbars(self, region: Region) -> Iterable[tuple[Widget, Region]]
horizontal_scrollbar_region,
scrollbar_corner_gap,
) = region.split(
-scrollbar_size_vertical,
-scrollbar_size_horizontal,
region.width - scrollbar_size_vertical,
region.height - scrollbar_size_horizontal,
)
if scrollbar_corner_gap:
yield self.scrollbar_corner, scrollbar_corner_gap
Expand All @@ -2719,7 +2719,7 @@ def _arrange_scrollbars(self, region: Region) -> Iterable[tuple[Widget, Region]]

elif show_vertical_scrollbar:
window_region, scrollbar_region = region.split_vertical(
-scrollbar_size_vertical
region.width - scrollbar_size_vertical
)
if scrollbar_region:
scrollbar = self.vertical_scrollbar
Expand All @@ -2728,7 +2728,7 @@ def _arrange_scrollbars(self, region: Region) -> Iterable[tuple[Widget, Region]]
yield scrollbar, scrollbar_region
elif show_horizontal_scrollbar:
window_region, scrollbar_region = region.split_horizontal(
-scrollbar_size_horizontal
region.height - scrollbar_size_horizontal
)
if scrollbar_region:
scrollbar = self.horizontal_scrollbar
Expand Down
21 changes: 21 additions & 0 deletions tests/test_containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,24 @@ def compose(self) -> ComposeResult:
middle = app.query_one(Middle)
assert middle.size.width == 4
assert middle.size.height == app.size.height


async def test_scrollbar_zero_thickness():
"""Ensuring that scrollbars can be set to zero thickness."""

class ScrollbarZero(App):
CSS = """* {
scrollbar-size: 0 0;
scrollbar-size-vertical: 0; /* just exercising the parser */
scrollbar-size-horizontal: 0; /* exercise the parser */
}
"""

def compose(self) -> ComposeResult:
with Vertical():
for _ in range(10):
yield Label("Hello, world!")

app = ScrollbarZero()
async with app.run_test(size=(8, 6)):
pass

0 comments on commit 1a0cd77

Please sign in to comment.