vaadin / web-components

A set of high-quality standards based web components for enterprise web applications. Part of Vaadin 20+
https://vaadin.com/docs/latest/components
426 stars 81 forks source link

SplitLayout: non-proportional splitter position #7410

Open rolfsmeds opened 1 month ago

rolfsmeds commented 1 month ago

Describe your motivation

The splitter position is currently always proportional to the width of the SplitLayout, which means that, as the SplitLayout shrinks and grows along the split's axis, both sides of the split scale proportionately.

Screen Recording 2024-05-14 at 14 35 23

This is fine in many cases, but sometimes you would need one side to stay unchanged, so that only the other side of the split scales (until the SplitLayout's total size is smaller than the "fixed" side of course).

Describe the solution you'd like

A way to set the splitter position to be "fixed" in relation to one of the sides, e.g. through an API that lets you define either side as the "split position anchor".

(In order to really make this work properly in the Flow component, it would also need a split position setter overload that takes a non-percentual size as argument, e.g. setSplitterPosition("300px")).

Describe alternatives you've considered

No response

Additional context

No response

JayKayDeon commented 1 month ago

Some inspiration: there is a component for the angular framework that offers some advanced options for nesting layouts (https://angular-split.github.io/). Using that split-component you can easily do something like this:

split-panel

Note: the middle (yellow) area has a minimum width, moving the left section will respect this one...

DiegoCardoso commented 1 month ago

A prototype that implements the feature can be found on this branch: https://github.com/vaadin/web-components/tree/proto/split-layout/split-position-anchor.

The main difference is to set the flex-basis of the element to be used as the anchor with its initial size (width or height) alongside changing its flex-grow and flex-shrink to 0, to make it always have the defined size. That can be verified working in the example below:

https://github.com/vaadin/web-components/assets/262432/f4ba0656-670d-4bf8-8e77-a7c80803d77b

Some findings:

tomivirkki commented 1 month ago

Hi @JayKayDeon, a somewhat similar-looking layout can be produced with two split layouts using the following setup. Not sure if this fully covers your use case:

<vaadin-split-layout style="width: 900px; height: 400px; outline: 1px solid black">
  <div>Left</div>
  <vaadin-split-layout style="height: 100%">
    <div style="min-width: 300px; background: lightyellow">Middle</div>
    <div style="max-width: 300px">Right</div>
  </vaadin-split-layout>
</vaadin-split-layout>

https://github.com/vaadin/web-components/assets/1222264/cb9d9dbe-3d68-40d2-b045-55d46f7f19e7


Update by @DiegoCardoso

The same example, but with Flow:

SplitLayout outerLayout = new SplitLayout();
SplitLayout innerLayout = new SplitLayout();
outerLayout.addToPrimary(new Span("left"));
outerLayout.addToSecondary(innerLayout);
innerLayout.addToPrimary(new Span("middle"));
innerLayout.addToSecondary(new Span("right"));

outerLayout.getStyle().setOutline("1px solid black");
outerLayout.setHeight("400px");
outerLayout.setWidth("900px");

innerLayout.setPrimaryStyle("background", "lightyellow");

// This is the important part
innerLayout.setPrimaryStyle("min-width", "300px");
innerLayout.setSecondaryStyle("max-width", "300px");

add(outerLayout);