[kbn-grid-layout] Remove use of fr unit (#208437)

Closes https://github.com/elastic/kibana/issues/208305

## Summary

This PR is a better solution for the issue described in
https://github.com/elastic/kibana/pull/208247. In that PR, we found that
the drag preview was causing panels to resize unnecessarily at seemingly
random occurrences, which was causing huge lag spikes and errors to be
thrown. While making the drag preview absolute positioned did resolve
that problem, it caused other issues (such as [this
one](https://github.com/elastic/kibana/issues/208305)) because the drag
preview no longer took up height in the parent.

Therefore, we decided to revisit this and, upon further investigation,
we found that the resize observers were **specifically** firing whenever
the viewport has a width that cannot be evenly divided into 48 columns,
which causes inconsistent rounding of pixels for each column on render.
The reason the drag preview in particular made this issue more apparent
is because, when rendering it as a `block`, it is causing the DOM to
repaint as it changes target column + row - which then caused the CSS
grid columns to "flicker" between widths that differed by less than half
a pixel. In the following GIF, you can see this flicker in the panel
widths as I drag another panel around:

![Jan-27-2025
12-28-57](https://github.com/user-attachments/assets/e19aacab-c43a-4541-aa57-b260da0cf4c9)

This then repeatedly triggered `resizeObservers` for panels that had
them.

Instead of relying on the `fr` unit, which is giving us inconsistent
column widths as shown above (most likely due to a rounding bug with the
`fr` unit in Chrome, since it works fine in Firefox), I have instead
migrated to a more static way of calculating `grid-template-columns` by
simply subtracting the pixels that the gutters take up from `100%` in
order to determine the width of a column. This still resolves the resize
observer problem, but it does so while still allowing the drag preview
to be rendered as a block.

### Checklist

- [x] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Hannah Mudge 2025-01-28 14:17:33 -07:00 committed by GitHub
parent 188823e972
commit 8ba2179096
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 8 additions and 6 deletions

View file

@ -39,10 +39,10 @@ export const DragPreview = ({
} else {
const panel = proposedGridLayout[rowIndex].panels[activePanel.id];
dragPreviewRef.current.style.display = 'block';
dragPreviewRef.current.style.height = `calc(1px * (${panel.height} * (var(--kbnGridRowHeight) + var(--kbnGridGutterSize)) - var(--kbnGridGutterSize)))`;
dragPreviewRef.current.style.width = `calc(1px * (${panel.width} * (var(--kbnGridColumnWidth) + var(--kbnGridGutterSize)) - var(--kbnGridGutterSize)))`;
dragPreviewRef.current.style.top = `calc(1px * (${panel.row} * (var(--kbnGridRowHeight) + var(--kbnGridGutterSize))))`;
dragPreviewRef.current.style.left = `calc(1px * (${panel.column} * (var(--kbnGridColumnWidth) + var(--kbnGridGutterSize))))`;
dragPreviewRef.current.style.gridColumnStart = `${panel.column + 1}`;
dragPreviewRef.current.style.gridColumnEnd = `${panel.column + 1 + panel.width}`;
dragPreviewRef.current.style.gridRowStart = `${panel.row + 1}`;
dragPreviewRef.current.style.gridRowEnd = `${panel.row + 1 + panel.height}`;
}
});
@ -61,7 +61,6 @@ export const DragPreview = ({
css={css`
display: none;
pointer-events: none;
position: absolute;
`}
/>
);

View file

@ -46,7 +46,10 @@ export const GridRow = ({
const { columnCount } = gridLayoutStateManager.runtimeSettings$.getValue();
return css`
grid-auto-rows: calc(var(--kbnGridRowHeight) * 1px);
grid-template-columns: repeat(${columnCount}, minmax(0, 1fr));
grid-template-columns: repeat(
${columnCount},
calc((100% - (var(--kbnGridGutterSize) * ${columnCount - 1}px)) / ${columnCount})
);
gap: calc(var(--kbnGridGutterSize) * 1px);
`;
}, [gridLayoutStateManager]);