-
Notifications
You must be signed in to change notification settings - Fork 815
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
Input
wider than widgets sized the same
#3721
Comments
Work-in-progress of adding an edit screen for bookmarks. This will be used for adding new bookmarks and editing existing ones. Something that needs to be added is a tag suggestion facility -- perhaps using the autocomplete or something; need to look into that. Textualize/textual#3721 is currently causing the layout to not be as good as it could be, and there's also the issue of how TextArea works meaning that: - There's no simple coloring. - There's no easy way to handle going into light mode. - There's no way to have the cursor not be visible when not focused. Some of these things will just have to be so until changes are made in Textual itself.
I wondered whether it was something about the box sizing, but it's not. Also, this happens with h and w units but not with absolute widths, vh, and vw. |
You've probably figured this out already, but this seems to be due to the If you add the same padding to the other widgets in your example, they display the same width. This possibly suggests a bug with how the percentage width is calculated, where it isn't properly taking into account padding? I don't quite understand why the width is 2 columns wider than than 4 though... |
I meant to say that the issue could be a rule It may very well just be that the style I'll stop speculating and leave this for whomever picks up the issue to solve it. |
I think I might have narrowed it down to these lines: Line 991 in a64a0d2
Lines 1018 to 1019 in a64a0d2
I confess I'm struggling a bit to follow the code, but here's what seems to be happening if we take my example app below.
The [EDIT: Sorry I've realised this also wouldn't calculate the correct size if from textual.app import App, ComposeResult
from textual.containers import Container
from textual.widgets import Static
class PercentWidthTestApp(App):
CSS = """
Container {
width: 100;
}
Static {
padding: 0 2;
width: 50%;
}
"""
def compose(self) -> ComposeResult:
with Container():
yield Static()
if __name__ == "__main__":
app = PercentWidthTestApp()
app.run() |
Based on my findings above, I'm wondering if the sizing calculation instead should be something like this: @@ -1007,6 +1007,9 @@ class Widget(DOMNode):
is_auto_width = styles.width and styles.width.is_auto
is_auto_height = styles.height and styles.height.is_auto
+ is_percent_width = styles.width and styles.width.unit == Unit.WIDTH
+ is_percent_height = styles.height and styles.height.unit == Unit.HEIGHT
+
# Container minus padding and border
content_container = container - gutter.totals
# The container including the content
@@ -1029,6 +1032,13 @@ class Widget(DOMNode):
and self._has_relative_children_width
):
content_width = Fraction(content_container.width)
+ elif is_percent_width:
+ styles_width = styles.width
+ content_width = styles_width.resolve(
+ container - styles.margin.totals, viewport, width_fraction
+ )
+ if is_border_box:
+ content_width -= gutter.width
else:
# An explicit width
styles_width = styles.width
@@ -1073,6 +1083,13 @@ class Widget(DOMNode):
and self._has_relative_children_height
):
content_height = Fraction(content_container.height)
+ elif is_percent_height:
+ styles_height = styles.height
+ content_height = styles_height.resolve(
+ container - styles.margin.totals, viewport, height_fraction
+ )
+ if is_border_box:
+ content_height -= gutter.height
else:
styles_height = styles.height
# Explicit height set My regression test passes, but there are 9 mismatched snapshots. But these mostly look like examples of widgets with a percent size and padding. async def test_widget_percent_size_with_padding():
"""Regression test for https://github.com/Textualize/textual/issues/3721"""
class PercentSizeTestApp(App):
CSS = """
Container {
height: 100;
width: 100;
}
Static {
height: 50%;
width: 50%;
padding: 2;
}
"""
def compose(self) -> ComposeResult:
with Container():
yield Static()
app = PercentSizeTestApp()
async with app.run_test() as pilot:
widget = pilot.app.query_one(Static)
assert widget.content_size == Size(46, 46)
assert widget.outer_size == Size(50, 50) |
It does look like percentage widths (and probably height) don't account for padding. It should, 50% with border-box should always be literally half the width. |
The other widths are off by one. App codefrom textual.app import App, ComposeResult
from textual.containers import Container
from textual.widgets import Input, TextArea, Static, Button
class InputVsTextArea(App[None]):
CSS = """
Screen > Container > *, Screen > Container > *:focus {
width: 50%;
height: 1fr;
border: solid red;
box-sizing: border-box;
}
"""
def compose(self) -> ComposeResult:
yield Static("1234567890" * 10)
with Container():
yield TextArea()
yield Input()
yield Static()
yield Button()
if __name__ == "__main__":
InputVsTextArea().run() |
I missed this before, but presumably With border only:
With extra padding:
|
Yup. Your diff above seems to do pretty much the trick. |
Thanks Rodrigo but honestly no need! My fix above is a bit rough and ready so no doubt you'll find a better solution! |
😭 the issue also affects max/min dimensions. |
ASSUMPTION: The margin of a widget is NOT taken into account when computing its size. E.g., if the terminal has width 100 and a widget has margin of 10 and a width of 100% or 100 or 100w or 100vw, its height _will_ be 100 and not 80. The original fix to #3721 introduced a new branch in the 'if elif else' branch that determines how to compute the width/height of widgets but as I kept digging, I realised calculations were 'off by one' in a couple of other places. Further debugging eventually revealed that the 'fix' actually results in a simplification of the code.
ASSUMPTION: The margin of a widget is NOT taken into account when computing its size. E.g., if the terminal has width 100 and a widget has margin of 10 and a width of 100% or 100 or 100w or 100vw, its height _will_ be 100 and not 80. The original fix to #3721 introduced a new branch in the 'if elif else' branch that determines how to compute the width/height of widgets but as I kept digging, I realised calculations were 'off by one' in a couple of other places. Further debugging eventually revealed that the 'fix' actually results in a simplification of the code. Co-authored-by: TomJGooding <[email protected]>
Don't forget to star the repository! Follow @textualizeio for Textual updates. |
I've not dived into why this is, but I just noticed it while working on something else and wanted to make a note for further checking. If you have a collection of widgets, all with the same width,
Input
stands out as not being the same width as the others:Possible down to something in its
DEFAULT_CSS
? Whatever the cause, it should probably really line up with the other widgets when at the same width.The text was updated successfully, but these errors were encountered: