This library relies on the browser as much as possible to do the layout calculations.
There are a lot of ways you could write a window splitter, but the requirements drive the approach.
For my ideal window splitter I want the following:
For what is essentially a line, there is a lot to get right :)
With CSS we have a few options for how we could do the layout.
display: block
Here we would have no help from the browser on what size the panels should be. We would have to do all the calculations ourselves. So no a fit for this library.
display: flex
Here the browser starts to help us out.
With flex we can define the size of the panels using percentages.
This is a large improvement over display: block
but it’s still not enough.
If we want to be able to support pixel based constraints the library has to do a lot more work.
To make flex
work with pixel based constraints we would have to:
This is cumbersome and pretty error prone. Conerting back to just a percentage makes it much harder to enforce pixel constraints both when resizing the page and when reloading at a different screen size.
display: grid
With grid
we have actually have all we need to implement the library.
CSS Grids can define the min/max of a column in both percentage and pixels.
Since we can define the layout for the window splitter entirely in CSS we get the following benefits:
The main downside to grid is that it’s easier to create and “invalid” layouts that don’t fill the area becuase of min/max constraints.
In a flex
you can ganuntee the width of the group will be filled, at the cost of accuracy.
The core of the resizing algorithm is built around applying small deltas to panels relative to their the resize handles.
As much as possible we try to rely on the browser to do the layout. During the initial layout we rely on CSS grid and a group might be defined like this:
grid-template-columns: minmax(100px, 1fr) 1px minmax(100px, 300px);
Once the user starts resizing we start a 3 step process to update the layout.
prepareItems
- The size of the group has been measure and we
can convert all the panel sizes into pixels. Converting into pixels
makes doing the math for the updates easier.
grid-template-columns: 500px 1px 300px;
updateLayout
- This is where the actual updates are applied.
This is where the user’s drag interactions are applied. We also
use this to collapse/expand panels by simulating a drag interaction.
grid-template-columns: 490px 1px 310px;
commitLayout
- Once the updates have been applied we convert the
updated sizes back into a format that allows for the benefits mentioned above.
grid-template-columns: minmax(100px, min(calc(0.06117 * (100% - 1px)), 100%)) 1px minmax(100px, min(calc(0.0387 * (100% - 1px)), 300px));