Skip to content

Commit 5943b18

Browse files
committed
Address review feedback: ColumnFrozen type + CSS dedup
1 parent 820e311 commit 5943b18

11 files changed

Lines changed: 97 additions & 59 deletions

File tree

src/DataGrid.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ import { default as defaultRenderSortStatus } from './sortStatus';
7474
import { cellDragHandleClassname, cellDragHandleFrozenClassname } from './style/cell';
7575
import {
7676
rootClassname,
77-
frozenColumnShadowClassname,
7877
frozenColumnShadowEndClassname,
79-
viewportDraggingClassname,
78+
frozenColumnShadowEndTopClassname,
79+
frozenColumnShadowStartClassname,
8080
frozenColumnShadowTopClassname,
81-
frozenColumnShadowEndTopClassname
81+
viewportDraggingClassname
8282
} from './style/core';
8383
import SummaryRow from './SummaryRow';
8484

@@ -1292,7 +1292,7 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
12921292
{lastFrozenColumnIndex > -1 &&
12931293
renderFrozenShadow(
12941294
frozenShadowStyles,
1295-
frozenColumnShadowClassname,
1295+
frozenColumnShadowStartClassname,
12961296
frozenColumnShadowTopClassname
12971297
)}
12981298

src/GroupRow.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { classnames } from './utils';
66
import type { BaseRenderRowProps, GroupRow, Omit } from './types';
77
import { SELECT_COLUMN_KEY } from './Columns';
88
import GroupCell from './GroupCell';
9-
import { cell, cellFrozen, cellFrozenEnd } from './style/cell';
9+
import { cell, cellFrozen } from './style/cell';
1010
import { rowClassname, rowActiveClassname } from './style/row';
1111

1212
const groupRow = css`
@@ -15,9 +15,9 @@ const groupRow = css`
1515
background-color: var(--rdg-header-background-color);
1616
}
1717
18-
> .${cell}:not(:last-child, .${cellFrozen}, .${cellFrozenEnd}),
19-
> :nth-last-child(n + 2 of .${cellFrozen}),
20-
> :nth-child(n + 2 of .${cellFrozenEnd}) {
18+
> .${cell}:not(:last-child, .${cellFrozen}),
19+
> :nth-last-child(n + 2 of .rdg-cell-frozen),
20+
> :nth-child(n + 2 of .rdg-cell-frozen-end) {
2121
border-inline-end: none;
2222
}
2323
}

src/HeaderRow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import type {
1212
} from './types';
1313
import type { DataGridProps } from './DataGrid';
1414
import HeaderCell from './HeaderCell';
15-
import { cell, cellFrozen, cellFrozenEnd } from './style/cell';
15+
import { cell, cellFrozen } from './style/cell';
1616
import { rowActiveClassname } from './style/row';
1717

1818
type SharedDataGridProps<R, SR, K extends React.Key> = Pick<
@@ -44,7 +44,7 @@ const headerRow = css`
4444
position: sticky;
4545
}
4646
47-
& > .${cellFrozen}, & > .${cellFrozenEnd} {
47+
& > .${cellFrozen} {
4848
z-index: 3;
4949
}
5050
}

src/hooks/useCalculatedColumns.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { useMemo } from 'react';
22

33
import { clampColumnWidth, isStartFrozen, max, min } from '../utils';
4-
import type { CalculatedColumn, CalculatedColumnParent, ColumnOrColumnGroup, Omit } from '../types';
4+
import type {
5+
CalculatedColumn,
6+
CalculatedColumnParent,
7+
ColumnFrozen,
8+
ColumnOrColumnGroup,
9+
Omit
10+
} from '../types';
511
import { renderValue } from '../cellRenderers';
612
import { SELECT_COLUMN_KEY } from '../Columns';
713
import type { DataGridProps } from '../DataGrid';
@@ -94,7 +100,7 @@ export function useCalculatedColumns<R, SR>({
94100
continue;
95101
}
96102

97-
const frozen: boolean | 'start' | 'end' = rawColumn.frozen ?? false;
103+
const frozen: ColumnFrozen = rawColumn.frozen ?? false;
98104

99105
const column: MutableCalculatedColumn<R, SR> = {
100106
...rawColumn,

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export type {
2929
CellRendererProps,
3030
ColSpanArgs,
3131
Column,
32+
ColumnFrozen,
3233
ColumnGroup,
3334
ColumnOrColumnGroup,
3435
ColumnWidth,

src/style/cell.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ export const cell = css`
3030

3131
export const cellClassname = `rdg-cell ${cell}`;
3232

33+
// Single shared sticky/z-index rule reused by both edge-frozen variants.
34+
// Selectors that need to distinguish start vs end use the marker classes
35+
// (`.rdg-cell-frozen` / `.rdg-cell-frozen-end`) directly rather than this ecij identifier.
3336
export const cellFrozen = css`
3437
@layer rdg.Cell {
3538
position: sticky;
@@ -39,16 +42,7 @@ export const cellFrozen = css`
3942
`;
4043

4144
export const cellFrozenClassname = `rdg-cell-frozen ${cellFrozen}`;
42-
43-
export const cellFrozenEnd = css`
44-
@layer rdg.Cell {
45-
position: sticky;
46-
/* Should have a higher value than 0 to show up above unfrozen cells */
47-
z-index: 1;
48-
}
49-
`;
50-
51-
export const cellFrozenEndClassname = `rdg-cell-frozen-end ${cellFrozenEnd}`;
45+
export const cellFrozenEndClassname = `rdg-cell-frozen-end ${cellFrozen}`;
5246

5347
const cellDragHandle = css`
5448
@layer rdg.DragHandle {

src/style/core.ts

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -92,61 +92,57 @@ const viewportDragging = css`
9292

9393
export const viewportDraggingClassname = `rdg-viewport-dragging ${viewportDragging}`;
9494

95-
// Add shadow after the last frozen cell
95+
// Common properties shared by both start- and end-edge frozen-column shadows.
96+
// Variants below add only the direction-dependent properties (gradient + scroll-state predicate).
9697
export const frozenColumnShadowClassname = css`
9798
position: sticky;
9899
width: 10px;
100+
pointer-events: none;
101+
z-index: 1;
102+
opacity: 1;
103+
transition: opacity 0.1s;
104+
105+
&:dir(rtl) {
106+
transform: scaleX(-1);
107+
}
108+
`;
109+
110+
const frozenColumnShadowStartOverrides = css`
99111
background-image: linear-gradient(
100112
to right,
101113
light-dark(rgb(0 0 0 / 15%), rgb(0 0 0 / 40%)),
102114
transparent
103115
);
104-
pointer-events: none;
105-
z-index: 1;
106-
107-
opacity: 1;
108-
transition: opacity 0.1s;
109116
110117
/* TODO: reverse 'opacity' and remove 'not' */
111118
@container rdg-root not scroll-state(scrollable: inline-start) {
112119
opacity: 0;
113120
}
114-
115-
&:dir(rtl) {
116-
transform: scaleX(-1);
117-
}
118121
`;
119122

120-
// Add shadow before the first end-frozen cell (mirror of the start shadow)
121-
export const frozenColumnShadowEndClassname = css`
122-
position: sticky;
123-
width: 10px;
123+
const frozenColumnShadowEndOverrides = css`
124124
background-image: linear-gradient(
125125
to left,
126126
light-dark(rgb(0 0 0 / 15%), rgb(0 0 0 / 40%)),
127127
transparent
128128
);
129-
pointer-events: none;
130-
z-index: 1;
131-
132-
opacity: 1;
133-
transition: opacity 0.1s;
134129
135130
/* TODO: reverse 'opacity' and remove 'not' */
136131
@container rdg-root not scroll-state(scrollable: inline-end) {
137132
opacity: 0;
138133
}
139-
140-
&:dir(rtl) {
141-
transform: scaleX(-1);
142-
}
143134
`;
144135

136+
// Add shadow after the last start-frozen cell
137+
export const frozenColumnShadowStartClassname = `${frozenColumnShadowClassname} ${frozenColumnShadowStartOverrides}`;
138+
139+
// Add shadow before the first end-frozen cell (mirror of the start shadow)
140+
export const frozenColumnShadowEndClassname = `${frozenColumnShadowClassname} ${frozenColumnShadowEndOverrides}`;
141+
145142
const topShadowClassname = css`
146143
/* render above header and summary rows */
147144
z-index: 2;
148145
`;
149146

150-
export const frozenColumnShadowTopClassname = `${frozenColumnShadowClassname} ${topShadowClassname}`;
151-
147+
export const frozenColumnShadowTopClassname = `${frozenColumnShadowStartClassname} ${topShadowClassname}`;
152148
export const frozenColumnShadowEndTopClassname = `${frozenColumnShadowEndClassname} ${topShadowClassname}`;

src/style/row.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { css } from 'ecij';
22

3-
import { cellFrozen, cellFrozenEnd } from './cell';
4-
53
export const row = css`
64
@layer rdg.Row {
75
display: grid;
@@ -27,20 +25,20 @@ export const row = css`
2725
border: var(--rdg-selection-width) solid var(--rdg-selection-color);
2826
}
2927
30-
& > .${cellFrozen}:first-child::before {
28+
& > .rdg-cell-frozen:first-child::before,
29+
& > .rdg-cell-frozen-end:last-child::after {
3130
content: '';
3231
display: inline-block;
3332
position: absolute;
3433
inset-block: 0;
34+
}
35+
36+
& > .rdg-cell-frozen:first-child::before {
3537
inset-inline-start: 0;
3638
border-inline-start: var(--rdg-selection-width) solid var(--rdg-selection-color);
3739
}
3840
39-
& > .${cellFrozenEnd}:last-child::after {
40-
content: '';
41-
display: inline-block;
42-
position: absolute;
43-
inset-block: 0;
41+
& > .rdg-cell-frozen-end:last-child::after {
4442
inset-inline-end: 0;
4543
border-inline-end: var(--rdg-selection-width) solid var(--rdg-selection-color);
4644
}

src/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export interface Column<TRow, TSummaryRow = unknown> {
4848
readonly colSpan?: Maybe<(args: ColSpanArgs<TRow, TSummaryRow>) => Maybe<number>>;
4949
/** Determines whether column is frozen, and on which edge.
5050
* `true` is an alias for `'start'` for backwards compatibility. */
51-
readonly frozen?: Maybe<boolean | 'start' | 'end'>;
51+
readonly frozen?: Maybe<ColumnFrozen>;
5252
/** Enable resizing of the column */
5353
readonly resizable?: Maybe<boolean>;
5454
/** Enable sorting of the column */
@@ -89,7 +89,7 @@ export interface CalculatedColumn<TRow, TSummaryRow = unknown> extends Column<TR
8989
readonly resizable: boolean;
9090
readonly sortable: boolean;
9191
readonly draggable: boolean;
92-
readonly frozen: boolean | 'start' | 'end';
92+
readonly frozen: ColumnFrozen;
9393
readonly renderCell: (props: RenderCellProps<TRow, TSummaryRow>) => ReactNode;
9494
readonly renderHeaderCell: (props: RenderHeaderCellProps<TRow, TSummaryRow>) => ReactNode;
9595
}
@@ -332,6 +332,7 @@ export interface SortColumn {
332332
}
333333

334334
export type CellNavigationMode = 'NONE' | 'CHANGE_ROW';
335+
export type ColumnFrozen = boolean | 'start' | 'end';
335336
export type SortDirection = 'ASC' | 'DESC';
336337

337338
export type ColSpanArgs<TRow, TSummaryRow> =

src/utils/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import type { CalculatedColumn, CalculatedColumnOrColumnGroup, Maybe } from '../types';
1+
import type {
2+
CalculatedColumn,
3+
CalculatedColumnOrColumnGroup,
4+
ColumnFrozen,
5+
Maybe
6+
} from '../types';
27

38
export * from './activePositionUtils';
49
export * from './colSpanUtils';
@@ -40,6 +45,6 @@ export function getHeaderCellRowSpan<R, SR>(
4045
}
4146

4247
// Shared predicate — `frozen: true` is the backwards-compatible alias for `frozen: 'start'`.
43-
export function isStartFrozen(frozen: boolean | 'start' | 'end'): boolean {
48+
export function isStartFrozen(frozen: ColumnFrozen): boolean {
4449
return frozen === true || frozen === 'start';
4550
}

0 commit comments

Comments
 (0)