Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect width calculation with buttons in a horizontal container that has width: auto #4024

Closed
davep opened this issue Jan 15, 2024 · 2 comments · Fixed by #4317
Closed
Labels
bug Something isn't working Task

Comments

@davep
Copy link
Contributor

davep commented Jan 15, 2024

This might be less specific that the subject suggests, but so far it's the only combination I've been able to use to create this problem. Given the following code, and given a sufficiently-sized terminal (in respect to width), you would expect every Horizontal in the result to reach the edge of the screen and either clip its content (for width: 1fr) or have itself be clipped (width: auto).

from textual.app import App, ComposeResult
from textual.containers import Horizontal
from textual.widgets import Button, Label

class HorizontalWidthAutoApp(App[None]):

    CSS = """
    Horizontal {
        border: solid red;
        height: auto;

        &.auto {
            width: auto;
        }

        Button, Label {
            margin-left: 1;
        }
    }
    """

    def compose(self) -> ComposeResult:
        with Horizontal(classes="auto"):
            for n in range(10):
                yield Button(f"{n} This is a very wide button {n}")
        with Horizontal():
            for n in range(10):
                yield Button(f"{n} This is a very wide button {n}")
        with Horizontal(classes="auto"):
            for n in range(10):
                yield Label(f"{n} This is a very wide label {n}")
        with Horizontal():
            for n in range(10):
                yield Label(f"{n} This is a very wide label {n}")

if __name__ == "__main__":
    HorizontalWidthAutoApp().run()

The result, however, is different from what would be expected:

Screenshot 2024-01-15 at 15 29 02

In this case the width: auto Horizontal that contains Buttons seems to come up short.

@davep davep added bug Something isn't working Task labels Jan 15, 2024
davep added a commit to davep/textual-sandbox that referenced this issue Jan 15, 2024
@TomJGooding
Copy link
Contributor

TomJGooding commented Jan 15, 2024

It looks like the key difference is that the Button text can wrap, so the container's auto width is calcuated based on the minimum width of the widget rather than the optimal width of the renderable?

image

from textual.app import App, ComposeResult
from textual.containers import Horizontal
from textual.widgets import Button


class HorizontalWidthAutoApp(App[None]):
    CSS = """
    Horizontal {
        border: solid red;
        height: auto;
        width: auto;
    }

    Button {
        margin-left: 1;
    }
    """

    def compose(self) -> ComposeResult:
        with Horizontal(classes="auto"):
            yield Button("This is a very wide button")

        with Horizontal(classes="auto"):
            yield Button("This is a very wide button")
            yield Button("This is a very wide button")


if __name__ == "__main__":
    HorizontalWidthAutoApp().run()

Copy link

Don't forget to star the repository!

Follow @textualizeio for Textual updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Task
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants