-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Rework frozen column shadow #3969
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
Changes from all commits
366b9c8
8004dc8
b5748e7
30d3c5f
532b09b
5e74cdc
128146f
0213833
1d7799d
a796ed6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -69,7 +69,12 @@ import type { PartialPosition } from './ScrollToCell'; | |
| import ScrollToCell from './ScrollToCell'; | ||
| import { default as defaultRenderSortStatus } from './sortStatus'; | ||
| import { cellDragHandleClassname, cellDragHandleFrozenClassname } from './style/cell'; | ||
| import { rootClassname, viewportDraggingClassname } from './style/core'; | ||
| import { | ||
| rootClassname, | ||
| frozenColumnShadowClassname, | ||
| viewportDraggingClassname, | ||
| frozenColumnShadowTopClassname | ||
| } from './style/core'; | ||
| import SummaryRow from './SummaryRow'; | ||
|
|
||
| export interface SelectCellState extends Position { | ||
|
|
@@ -368,6 +373,10 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr | |
| const minRowIdx = -headerAndTopSummaryRowsCount; | ||
| const mainHeaderRowIdx = minRowIdx + groupedColumnHeaderRowsCount; | ||
| const maxRowIdx = rows.length + bottomSummaryRowsCount - 1; | ||
| const frozenShadowStyles: React.CSSProperties = { | ||
| gridColumnStart: lastFrozenColumnIndex + 2, | ||
| insetInlineStart: totalFrozenColumnWidth | ||
| }; | ||
|
|
||
| const [selectedPosition, setSelectedPosition] = useState( | ||
| (): SelectCellState | EditCellState<R> => ({ idx: -1, rowIdx: minRowIdx - 1, mode: 'SELECT' }) | ||
|
|
@@ -1269,11 +1278,11 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr | |
| const isSummaryRowSelected = selectedPosition.rowIdx === summaryRowIdx; | ||
| const top = | ||
| clientHeight > totalRowHeight | ||
| ? gridHeight - summaryRowHeight * (bottomSummaryRows.length - rowIdx) | ||
| ? gridHeight - summaryRowHeight * (bottomSummaryRowsCount - rowIdx) | ||
| : undefined; | ||
| const bottom = | ||
| top === undefined | ||
| ? summaryRowHeight * (bottomSummaryRows.length - 1 - rowIdx) | ||
| ? summaryRowHeight * (bottomSummaryRowsCount - 1 - rowIdx) | ||
| : undefined; | ||
|
|
||
| return ( | ||
|
|
@@ -1298,6 +1307,47 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr | |
| )} | ||
| </DataGridDefaultRenderersContext> | ||
|
|
||
| {lastFrozenColumnIndex > -1 && ( | ||
| <> | ||
| <div | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is is possible or a good idea to use a single div instead? Can it cause performance issues?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not really, for example: If we have no rows between the last row and the bottom summary, then we don't want to render a shadow for non-existent cells. Also, if you scroll very fast then rows/cells may not be rendered yet, in that case I think it's better to not render the shadow as well.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. makes sense. |
||
| className={frozenColumnShadowTopClassname} | ||
| style={{ | ||
| ...frozenShadowStyles, | ||
| gridRowStart: 1, | ||
| gridRowEnd: headerRowsCount + 1 + topSummaryRowsCount, | ||
| insetBlockStart: 0 | ||
| }} | ||
| /> | ||
|
|
||
| {rows.length > 0 && ( | ||
| <div | ||
| className={frozenColumnShadowClassname} | ||
| style={{ | ||
| ...frozenShadowStyles, | ||
| gridRowStart: headerAndTopSummaryRowsCount + rowOverscanStartIdx + 1, | ||
| gridRowEnd: headerAndTopSummaryRowsCount + rowOverscanEndIdx + 2 | ||
| }} | ||
| /> | ||
| )} | ||
|
|
||
| {bottomSummaryRows != null && bottomSummaryRowsCount > 0 && ( | ||
| <div | ||
| className={frozenColumnShadowTopClassname} | ||
| style={{ | ||
| ...frozenShadowStyles, | ||
| gridRowStart: headerAndTopSummaryRowsCount + rows.length + 1, | ||
| gridRowEnd: headerAndTopSummaryRowsCount + rows.length + 1 + bottomSummaryRowsCount, | ||
| insetBlockStart: | ||
| clientHeight > totalRowHeight | ||
| ? gridHeight - summaryRowHeight * bottomSummaryRowsCount | ||
| : undefined, | ||
| insetBlockEnd: clientHeight > totalRowHeight ? undefined : 0 | ||
| }} | ||
| /> | ||
| )} | ||
| </> | ||
| )} | ||
|
|
||
| {getDragHandle()} | ||
|
|
||
| {/* render empty cells that span only 1 column so we can safely measure column widths, regardless of colSpan */} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,7 +16,6 @@ const root = css` | |
| --rdg-selection-width: 2px; | ||
| --rdg-selection-color: hsl(207, 75%, 66%); | ||
| --rdg-font-size: 14px; | ||
| --rdg-cell-frozen-box-shadow: 2px 0 5px -2px rgba(136, 136, 136, 0.3); | ||
| --rdg-border-width: 1px; | ||
| --rdg-summary-border-width: calc(var(--rdg-border-width) * 2); | ||
| --rdg-color: light-dark(#000, #ddd); | ||
|
|
@@ -38,10 +37,6 @@ const root = css` | |
| color-scheme: light; | ||
| } | ||
|
|
||
| &:dir(rtl) { | ||
| --rdg-cell-frozen-box-shadow: -2px 0 5px -2px rgba(136, 136, 136, 0.3); | ||
| } | ||
|
|
||
| display: grid; | ||
|
|
||
| accent-color: light-dark(hsl(207deg 100% 29%), hsl(207deg 100% 79%)); | ||
|
|
@@ -59,6 +54,9 @@ const root = css` | |
| color: var(--rdg-color); | ||
| font-size: var(--rdg-font-size); | ||
|
|
||
| container-name: rdg-root; | ||
| container-type: scroll-state; | ||
|
|
||
| /* needed on Firefox to fix scrollbars */ | ||
| &::before { | ||
| content: ''; | ||
|
|
@@ -92,3 +90,35 @@ const viewportDragging = css` | |
| `; | ||
|
|
||
| export const viewportDraggingClassname = `rdg-viewport-dragging ${viewportDragging}`; | ||
|
|
||
| // Add shadow after the last frozen cell | ||
| export const frozenColumnShadowClassname = css` | ||
| position: sticky; | ||
| width: 10px; | ||
| background-image: linear-gradient( | ||
| to right, | ||
| light-dark(rgb(0 0 0 / 15%), rgb(0 0 0 / 40%)), | ||
| transparent | ||
| ); | ||
|
Comment on lines
+97
to
+102
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The shadow is wider/stronger than before, let me know if you think we should tweak it.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM |
||
| pointer-events: none; | ||
| z-index: 1; | ||
|
|
||
| opacity: 1; | ||
| transition: opacity 0.1s; | ||
|
|
||
| /* TODO: reverse 'opacity' and remove 'not' */ | ||
| @container rdg-root not scroll-state(scrollable: inline-start) { | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Firefox/Safari will always show the shadow until they support
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is great |
||
| opacity: 0; | ||
| } | ||
|
|
||
| &:dir(rtl) { | ||
| transform: scaleX(-1); | ||
| } | ||
| `; | ||
|
|
||
| const topShadowClassname = css` | ||
| /* render above header and summary rows */ | ||
| z-index: 2; | ||
| `; | ||
|
|
||
| export const frozenColumnShadowTopClassname = `${frozenColumnShadowClassname} ${topShadowClassname}`; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the best way I found to make it work in all scenarios, including column grouping.