Skip to content
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

Use grid layout for rows, split column metrics from compute columns #2272

Merged
merged 7 commits into from
Jan 13, 2021

Conversation

nstepien
Copy link
Contributor

@nstepien nstepien commented Jan 11, 2021

What's the fun in making a grid component if you don't use display: grid;?

image

@nstepien nstepien self-assigned this Jan 11, 2021
column.frozen = true;
column.rowGroup = true;
}
const columns = rawColumns.map(rawColumn => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only create 1 columns array now in this useMemo from 2 arrays before.
We also create the column object once, no more intermediary column object.


if (column.rowGroup) {
groupBy.push(column.key);
column.groupFormatter ??= ToggleGroupFormatter;
Copy link
Contributor Author

@nstepien nstepien Jan 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Browsers already support this syntax, and babel transpiles it. 👍
https://caniuse.com/mdn-javascript_operators_logical_nullish_assignment
Bonus point: it doesn't re-assign the value if it already exists.
https://v8.dev/blog/v8-release-85#logical-assignment-operators

};
}, [rawColumns, defaultFormatter, defaultResizable, defaultSortable, rawGroupBy]);

const { layoutCssVars, totalColumnWidth, totalFrozenColumnWidth, columnMetrics } = useMemo(() => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now compute column metrics in a separate useMemo, and store it in a separate Map.
That way we can, for example, resize columns without re-creating the column objects, and reducing re-renders.

totalColumnWidth: totalWidth,
groupBy
const layoutCssVars: Record<string, string> = {
'--template-columns': templateColumns
Copy link
Contributor Author

@nstepien nstepien Jan 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used for the grid-template-columns css property in all rows now.
That way we set the template on the root, and we don't have to update all rows/cells (in js).


for (let i = 0; i <= lastFrozenColumnIndex; i++) {
const column = columns[i];
layoutCssVars[`--frozen-left-${column.key}`] = `${columnMetrics.get(column)!.left}px`;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The frozen columns still need to know their left position otherwise position: sticky won't work.

@@ -1,37 +1,3 @@
import type { CalculatedColumn } from '../types';

export function getColumnScrollPosition<R, SR>(columns: readonly CalculatedColumn<R, SR>[], idx: number, currentScrollLeft: number, currentClientWidth: number): number {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This did way too much unnecessary work.

export function getCellStyle<R, SR>(column: CalculatedColumn<R, SR>): React.CSSProperties {
return column.frozen
? { left: `var(--frozen-left-${column.key})` }
: { gridColumnStart: column.idx + 1 };
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "picks" the correct grid column from the grid-template-columns, regardless of its DOM position.

@@ -1,8 +1,6 @@
.rdg-cell {
contain: strict;
contain: size layout style paint;
position: absolute;
height: inherit;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Height is set by the grid layout now.

@@ -1,11 +1,13 @@
.rdg-row {
contain: strict;
contain: size layout style paint;
display: flex;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We know that flex+sticky position cells can be buggy in Firefox, but I wonder if grid+sticky works fine or not.

@@ -1,11 +1,13 @@
.rdg-row {
contain: strict;
contain: size layout style paint;
display: flex;
display: grid;
grid-template-rows: var(--row-height);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This basically means that we only have 1 row in this grid.

@nstepien nstepien marked this pull request as ready for review January 12, 2021 16:21
@nstepien nstepien changed the title Use grid layout for rows Use grid layout for rows, split column metrics from compute columns Jan 12, 2021
Copy link
Contributor

@amanmahajan7 amanmahajan7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great overall

src/utils/columnUtils.ts Show resolved Hide resolved
}
}

const unallocatedWidth = viewportWidth - allocatedWidth;
const unallocatedColumnWidth = Math.max(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to use Math.max if we are using clampColumnWidth later?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't, I've removed it now, we also don't need to floor it, now columns will always fill all the available space when possible.
For a before/after comparison, open the columns reordering story, and resize the browser, you'll see that with Math.floor() there can be some space between the last column and the scrollbar.

@@ -58,15 +58,19 @@ export interface Column<TRow, TSummaryRow = unknown> {

export interface CalculatedColumn<TRow, TSummaryRow = unknown> extends Column<TRow, TSummaryRow> {
idx: number;
width: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if any formatter/editor uses width/left or not. What is the alternative if those values are needed? ref?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could pass them in editorProps if it's ever needed.

@nstepien nstepien merged commit b5de11b into canary Jan 13, 2021
@nstepien nstepien deleted the gridlayout branch January 13, 2021 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants