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

[EuiDataGrid] DRY out scrolling/scrollbar detections and add scroll border overlays #5563

Merged
merged 9 commits into from
Jan 27, 2022
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## [`main`](https://github.com/elastic/eui/tree/main)

- Updated `EuiDataGrid`s with scrolling content to always have a border around the grid body and any scrollbars ([#5563](https://github.com/elastic/eui/pull/5563))

**Bug fixes**

- Fixed EuiDataGrid height issue when in full-screen mode and with scrolling content ([#5557](https://github.com/elastic/eui/pull/5557))
Expand Down
5 changes: 4 additions & 1 deletion src-docs/src/views/datagrid/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ export default () => {
);

return (
<EuiPanel style={{ maxWidth: 400, height: 300 }} paddingSize="none">
<EuiPanel
style={{ maxWidth: 400, height: 300, overflow: 'hidden' }}
paddingSize="none"
>
<EuiDataGrid
aria-label="Container constrained data grid demo"
columns={columns}
Expand Down
6 changes: 5 additions & 1 deletion src-docs/src/views/datagrid/flex.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ export default () => {
<EuiPanel color="subdued">Sidebar</EuiPanel>
</EuiFlexItem>
<EuiFlexItem style={{ minWidth: 0 }}>
<EuiPanel style={{ height: 300 }} hasBorder paddingSize="none">
<EuiPanel
style={{ height: 300, overflow: 'hidden' }}
hasBorder
paddingSize="none"
>
<EuiDataGrid
aria-label="Container constrained data grid demo"
columns={columns}
Expand Down
48 changes: 46 additions & 2 deletions src/components/datagrid/_data_grid.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
.euiDataGrid__pagination {
padding-bottom: $euiSizeXS;
background: $euiColorLightestShade;
border-top: $euiBorderThin;
box-shadow: $euiBorderWidthThin 0 0 $euiBorderWidthThin $euiBorderColor; // Use box-shadow instead of border-top to avoid duplicating the border-bottom on grid cells
}
}

Expand All @@ -29,12 +29,14 @@
max-width: 100%;
width: 100%;
overflow: hidden;
z-index: 2; // Sits above the pagination below it, but below the controls above it
z-index: 1; // Sits below the controls above it and pagination below it
position: relative;
background: $euiColorEmptyShade;
font-feature-settings: 'tnum' 1; // Tabular numbers
}

.euiDataGrid__pagination {
z-index: 2; // Sits above the content above it
padding-top: $euiSizeXS;
flex-grow: 0;
}
Expand Down Expand Up @@ -65,3 +67,45 @@
@include euiScrollBar($euiColorDarkShade, $euiColorEmptyShade);
scroll-padding: 0;
}

.euiDataGrid__scrollOverlay {
position: absolute;
top: -1 * $euiBorderWidthThin; // Overlaps the toolbar border
right: 0;
bottom: 0;
left: 0;

// Ensure the underlying grid is still interactable
pointer-events: none;

// Ensure the scrolling data grid body always has border edges
// regardless of cell position
box-shadow: inset 0 0 0 $euiBorderWidthThin $euiBorderColor;
// Note that this *must* be an inset `box-shadow` and not `border`, because
// border will affect the relative position of the child scroll bar overlays
// and cause them to be off by the width of the border

// For grids with horizontal-only borders, only render a bottom 'border'
.euiDataGrid--bordersHorizontal & {
box-shadow: inset 0 (-2 * $euiBorderWidthThin) 0 (-1 * $euiBorderWidthThin) $euiBorderColor;
}

// Ensure the horizontal scrollbar has a top border
.euiDataGrid__scrollBarOverlayBottom {
position: absolute;
width: 100%;
height: $euiBorderWidthThin;
background-color: $euiBorderColor;
}

// Ensure the vertical scrollbar has a left border
.euiDataGrid__scrollBarOverlayRight {
position: absolute;
height: 100%;
width: $euiBorderWidthThin;
background-color: $euiBorderColor;
}

// Note: Scroll bar border positions are set via JS inline style, since
// JS has access to the exact OS scrollbar width/height and CSS doesn't
}
17 changes: 14 additions & 3 deletions src/components/datagrid/body/data_grid_body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {
import { useDefaultColumnWidth, useColumnWidths } from '../utils/col_widths';
import { useRowHeightUtils, useDefaultRowHeight } from '../utils/row_heights';
import { useHeaderFocusWorkaround } from '../utils/focus';
import { useScroll } from '../utils/scrolling';
import { useScrollBars, useScroll } from '../utils/scrolling';
import { DataGridSortingContext } from '../utils/sorting';
import { IS_JEST_ENVIRONMENT } from '../../../test';

Expand Down Expand Up @@ -253,6 +253,16 @@ export const EuiDataGridBody: FunctionComponent<EuiDataGridBodyProps> = (
const outerGridRef = useRef<HTMLDivElement | null>(null); // container that becomes scrollable
const innerGridRef = useRef<HTMLDivElement | null>(null); // container sized to fit all content

/**
* Scroll bars
*/
const {
scrollBarHeight,
hasVerticalScroll,
hasHorizontalScroll,
scrollBorderOverlay,
} = useScrollBars(outerGridRef, gridStyles.border);

/**
* Widths
*/
Expand Down Expand Up @@ -364,7 +374,7 @@ export const EuiDataGridBody: FunctionComponent<EuiDataGridBodyProps> = (
useScroll({
gridRef,
outerGridRef,
innerGridRef,
hasGridScrolling: hasVerticalScroll || hasHorizontalScroll,
headerRowHeight,
footerRowHeight,
visibleRowCount,
Expand Down Expand Up @@ -402,7 +412,7 @@ export const EuiDataGridBody: FunctionComponent<EuiDataGridBodyProps> = (
defaultRowHeight,
headerRowHeight,
footerRowHeight,
outerGridRef,
scrollBarHeight,
innerGridRef,
});

Expand Down Expand Up @@ -486,6 +496,7 @@ export const EuiDataGridBody: FunctionComponent<EuiDataGridBodyProps> = (
>
{Cell}
</Grid>
{scrollBorderOverlay}
</DataGridWrapperRowsContext.Provider>
) : null;
};
2 changes: 1 addition & 1 deletion src/components/datagrid/controls/_data_grid_toolbar.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.euiDataGrid__controls {
background: $euiPageBackgroundColor;
position: relative;
z-index: 3; // Needs to sit above the content blow that sits below it
z-index: 2; // Needs to sit above the content below it
border: $euiBorderThin;
padding: $euiSizeXS $euiSizeXS $euiSizeXS 0;
display: flex;
Expand Down
15 changes: 3 additions & 12 deletions src/components/datagrid/utils/grid_height_width.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const useUnconstrainedHeight = ({
defaultRowHeight,
headerRowHeight,
footerRowHeight,
outerGridRef,
scrollBarHeight,
innerGridRef,
}: {
rowHeightUtils: RowHeightUtils;
Expand All @@ -82,7 +82,7 @@ export const useUnconstrainedHeight = ({
defaultRowHeight: number;
headerRowHeight: number;
footerRowHeight: number;
outerGridRef: React.MutableRefObject<HTMLDivElement | null>;
scrollBarHeight: number;
innerGridRef: React.MutableRefObject<HTMLDivElement | null>;
}) => {
const { getCorrectRowIndex } = useContext(DataGridSortingContext);
Expand Down Expand Up @@ -127,21 +127,12 @@ export const useUnconstrainedHeight = ({
);
useUpdateEffect(forceRender, [innerWidth]);

// https://stackoverflow.com/a/5038256
const hasHorizontalScroll =
(outerGridRef.current?.scrollWidth ?? 0) >
(outerGridRef.current?.clientWidth ?? 0);
// https://stackoverflow.com/a/24797425
const scrollbarHeight = hasHorizontalScroll
? outerGridRef.current!.offsetHeight - outerGridRef.current!.clientHeight
: 0;

const unconstrainedHeight =
defaultRowHeight * (rowCountToAffordFor - knownRowCount) + // guess how much space is required for unknown rows
knownHeight + // computed pixel height of the known rows
headerRowHeight + // account for header
footerRowHeight + // account for footer
scrollbarHeight; // account for horizontal scrollbar
scrollBarHeight; // account for horizontal scrollbar

return unconstrainedHeight;
};
Expand Down
Loading