diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fd7a6873..0801fb9b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Rebuilt `DirectoryTree` with new `Tree` control. +- Empty containers with a dimension set to `"auto"` will now collapse instead of filling up the available space. - Container widgets now have default height of `1fr`. - The default `width` of a `Label` is now `auto`. diff --git a/src/textual/_layout.py b/src/textual/_layout.py index ca5233104..c263c13ee 100644 --- a/src/textual/_layout.py +++ b/src/textual/_layout.py @@ -67,7 +67,7 @@ class Layout(ABC): ) width = child_width if width is None else max(width, child_width) if width is None: - width = container.width + width = 0 return width @@ -86,7 +86,7 @@ class Layout(ABC): int: Content height (in lines). """ if not widget.displayed_children: - height = container.height + height = 0 else: placements, *_ = widget._arrange(Size(width, container.height)) height = max( diff --git a/src/textual/box_model.py b/src/textual/box_model.py index 18ca78225..be9b92fcc 100644 --- a/src/textual/box_model.py +++ b/src/textual/box_model.py @@ -124,7 +124,7 @@ def get_box_model( ) content_height = min(content_height, max_height) - content_height = max(Fraction(1), content_height) + content_height = max(Fraction(0), content_height) model = BoxModel( content_width + gutter.width, content_height + gutter.height, margin ) diff --git a/src/textual/layouts/horizontal.py b/src/textual/layouts/horizontal.py index 87ab7c28c..08d5f7077 100644 --- a/src/textual/layouts/horizontal.py +++ b/src/textual/layouts/horizontal.py @@ -73,7 +73,7 @@ class HorizontalLayout(Layout): int: Width of the content. """ if not widget.displayed_children: - width = container.width + width = 0 else: placements, *_ = widget._arrange(container) width = max( diff --git a/src/textual/widgets/_input.py b/src/textual/widgets/_input.py index f01587120..1d4b0e3f5 100644 --- a/src/textual/widgets/_input.py +++ b/src/textual/widgets/_input.py @@ -61,12 +61,13 @@ class Input(Widget, can_focus=True): border: tall $background; width: 100%; height: 1; + min-height: 1; } Input.-disabled { opacity: 0.6; } Input:focus { - border: tall $accent; + border: tall $accent; } Input>.input--cursor { background: $surface; diff --git a/tests/layouts/test_content_dimensions.py b/tests/layouts/test_content_dimensions.py new file mode 100644 index 000000000..1db259b4a --- /dev/null +++ b/tests/layouts/test_content_dimensions.py @@ -0,0 +1,28 @@ +import pytest + +from textual.layouts.grid import GridLayout +from textual.layouts.horizontal import HorizontalLayout +from textual.layouts.vertical import VerticalLayout +from textual.geometry import Size +from textual.widget import Widget + + +LAYOUTS = [GridLayout, HorizontalLayout, VerticalLayout] + + +@pytest.mark.parametrize("layout", LAYOUTS) +def test_empty_widget_height(layout): + """Test that an empty widget has height equal to 0.""" + l = layout() + # Make sure this measurement does not depend on the width. + assert l.get_content_height(Widget(), Size(80, 24), Size(80, 24), 24) == 0 + assert l.get_content_height(Widget(), Size(80, 24), Size(80, 24), 20) == 0 + assert l.get_content_height(Widget(), Size(80, 24), Size(80, 24), 10) == 0 + assert l.get_content_height(Widget(), Size(80, 24), Size(80, 24), 0) == 0 + + +@pytest.mark.parametrize("layout", LAYOUTS) +def test_empty_widget_width(layout): + """Test that an empty widget has width equal to 0.""" + l = layout() + assert l.get_content_width(Widget(), Size(80, 24), Size(80, 24)) == 0 diff --git a/tests/test_box_model.py b/tests/test_box_model.py index 889140041..c66f5a5b8 100644 --- a/tests/test_box_model.py +++ b/tests/test_box_model.py @@ -100,7 +100,7 @@ def test_width(): def test_height(): - """Test width settings.""" + """Test height settings.""" styles = Styles() one = Fraction(1) @@ -123,7 +123,7 @@ def test_height(): ) assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4)) - # Set width to 100 vw which should make it the width of the parent + # Set height to 100 vw which should make it the height of the parent styles.height = "100vh" box_model = get_box_model( @@ -131,7 +131,7 @@ def test_height(): ) assert box_model == BoxModel(Fraction(54), Fraction(24), Spacing(1, 2, 3, 4)) - # Set the width to 100% should make it fill the container size + # Set the height to 100% should make it fill the container size styles.height = "100%" box_model = get_box_model( @@ -156,6 +156,14 @@ def test_height(): ) assert box_model == BoxModel(Fraction(54), Fraction(10), Spacing(1, 2, 3, 4)) + # Set height to auto and set content height to 0 to check if box collapses. + styles.height = "auto" + + box_model = get_box_model( + styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, lambda *_: 0 + ) + assert box_model == BoxModel(Fraction(54), Fraction(0), Spacing(1, 2, 3, 4)) + def test_max(): """Check that max_width and max_height are respected."""