vaadin / flow-components

Java counterpart of Vaadin Web Components
101 stars 66 forks source link

FormLayout makes dialogs too wide #2201

Open cdir opened 2 years ago

cdir commented 2 years ago

I have a simple Dialog that contains a FormLayout. The FormLayout should have only one column and labels aside wich is set by a singe ResponsiveStep. The FormLayout contains of some FormItems with any fields, let's say there are three items with a TextField of defautlt width.

When I open the dialog, the width is calculated so that there is enough space for all three text fields next to each other.


    Dialog dialog = new Dialog();
    FormLayout formLayout = new FormLayout();
    formLayout.setResponsiveSteps(new ResponsiveStep("0", 1, LabelsPosition.ASIDE));
    formLayout.addFormItem(new TextField(), "Text1");
    formLayout.addFormItem(new TextField(), "Text2");
    formLayout.addFormItem(new TextField(), "Text3");
    dialog.add(formLayout);
    dialog.open();

image

rolfsmeds commented 2 years ago

Presumably related: https://github.com/vaadin/web-components/issues/949

rolfsmeds commented 2 years ago

This is caused by a peculiar combination of flexbox features: The default intrinsic width of a flexbox container (with flex-flow: row wrap) is the sum of the widths of its items, disregarding any wrapping of those items, i.e. as if there was no wrapping, so a percentual width on a flex item is calculated based on that sum. This means that a 100% wide flex item is as wide as the combined width of all items.

A heavily simplified example of this can be seen in example 1 here: https://codepen.io/rsmeds/pen/XWebNOo?editors=1100

FormLayout uses percentual widths to force its fields to wrap to multiple lines (~100% for single-column configurations). In an undefined-width FormLayout, this is equivalent to the combined width of all fields in the layout, so if there are 3 fields 200px wide each, the FormLayout's default intrinsic width is 3x200 = 600px, i.e. 3 times as wide as it would need to be.

I've tried tweaking various properties to work around this behavior, but the only fix I've found to work so far requires refactoring FormLayout to use css grid instead of flexbox (see examples 4 and 5 in the codepen). Since we've now dropped support for IE 11, this would be a good idea for other reasons as well, but is a breaking change that is very likely to affect existing applications.

A possible quick-fix would be to apply a width to the FormLayout, either in some absolute unit like px or em, but then you lose the automatic layouting based on contents, of course. Setting the width to min-content seems to achieve the desired result in single-column forms, but results in very compressed columns in multi-column configurations.