Horizontal layout and the default spacing of inner containers #2913
-
(I read a bunch of different guidance on layout but found nothing that clearly explains this, and apologies if I missed it.) I have a simple container that I will call an 'entry bar', which has a horizontal layout. I assumed that if I put other containers inside this 'tool bar' then their location would be dictated by their order of composition, respective widths, and any margins I gave their CSS classes. Yet, when I compose these inner containers they appear to be evenly distributed. I would rather that I control how they are distributed or "spaced" using something akin to width + margin-left or margin-right. If you look at the attached image you will see what I mean. The very first inner container shouldn't take up that much space. Any width or margin rules I entered seem to be not honored, so I got rid of them. It seemed the same when I used Is there something I can put in the outer 'entry bar' class that says I want to have the inner widgets fall one immediately after another? (For example, and I am making these up):
If you would rather I make the simplest example, I can and will. But I figured this is well-known behavior with an obvious solution. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 4 replies
-
Example runnable code that displays what you're doing would be useful, makes it easier to diagnose the cause and suggest solutions. |
Beta Was this translation helpful? Give feedback.
-
Okay. WIll do that. Thanks.
…On Tue, Jul 11, 2023 at 12:05 AM Dave Pearson ***@***.***> wrote:
Example runnable code that displays what you're doing would be useful,
makes it easier to diagnose the cause and suggest solutions.
—
Reply to this email directly, view it on GitHub
<#2913 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABLVAFRRE7SEXBPETETWAOTXPTUJNANCNFSM6AAAAAA2FG2TGE>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
Thank you for your answer. I have learned a lot from it. Especially the
HeaderField base class. That really simplifies everything.
It also seems like the DEFAULT_CSS is more readable so I am switching over
to that.
So since a Container uses ‘1fr’ then this wrapper class overrides the
wrapped widget. Got it!
Investigating further …
…On Thu, Jul 13, 2023 at 3:43 AM Dave Pearson ***@***.***> wrote:
First off, this is looking good; it's obvious you're getting a great grasp
of how to build with Textual.
Taking the AWSMonitorHeader in isolation, I see a few things going on
that, if tackled, might make this easier to reason about.
The first thing I'd suggest is that you're wrapping widgets in containers
more often than you really need to. If we take your AWSMonitorHeader
widget, you compose each of the sub-widgets inside individual containers;
that shouldn't really be necessary as each one of them is going to be a
container anyway. Given that Container is width and height 1fr out of the
box, you're always going to be fighting that. You could of course style
that in a different way, but I think it would make more sense to simplify
it away.
Here's my take on a simple app to provide a similar layout, which I hope
will illustrate what I'm thinking. Here I'm using DEFAULT_CSS to keep the
styling of the particular elements with their actual code, which can make
things easier to follow. I'm also using a Horizontal for the main header
control, making a base class for all of the label/input fields within the
header, and then grouping them all into a header widget.
from textual.app import App, ComposeResult
from textual.containers import Horizontal
from textual.widgets import Label, Checkbox, Input
class HeaderField(Horizontal):
DEFAULT_CSS = """
HeaderField {
width: auto;
}
HeaderField Label {
margin: 1;
}
"""
class AWSCheckbox(HeaderField):
def compose(self) -> ComposeResult:
yield Label("AWS:")
yield Checkbox()
class AMIId(HeaderField):
DEFAULT_CSS = """
AMIId Input {
width: 20;
}
"""
def compose(self) -> ComposeResult:
yield Label("AMI ID:")
yield Input()
class Version(HeaderField):
DEFAULT_CSS = """
Version Input {
width: 15;
}
"""
def compose(self) -> ComposeResult:
yield Label("Ver:")
yield Input()
class Motto(HeaderField):
DEFAULT_CSS = """
Motto Input {
width: 25;
}
"""
def compose(self) -> ComposeResult:
yield Label("Motto:")
yield Input()
class ExampleHeader(HeaderField):
DEFAULT_CSS = """
ExampleHeader {
border: solid white;
height: 5;
width: 1fr;
}
"""
def compose(self) -> ComposeResult:
yield AWSCheckbox()
yield AMIId()
yield Version()
yield Motto()
class LayoutExampleApp(App[None]):
def compose(self) -> ComposeResult:
yield ExampleHeader()
if __name__ == "__main__":
LayoutExampleApp().run()
Does that help in some way?
—
Reply to this email directly, view it on GitHub
<#2913 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABLVAFURZ2HDVAT3GNJIXJTXP67MDANCNFSM6AAAAAA2FG2TGE>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
First off, this is looking good; it's obvious you're getting a great grasp of how to build with Textual.
Taking the
AWSMonitorHeader
in isolation, I see a few things going on that, if tackled, might make this easier to reason about.The first thing I'd suggest is that you're wrapping widgets in containers more often than you really need to. If we take your AWSMonitorHeader widget, you compose each of the sub-widgets inside individual containers; that shouldn't really be necessary as each one of them is going to be a container anyway. Given that
Container
iswidth
andheight
1fr
out of the box, you're always going to be fighting that. You could of course style that in a different way, but …