Skip to content

Commit

Permalink
Fix footer column widths
Browse files Browse the repository at this point in the history
  • Loading branch information
chandlerprall committed Dec 21, 2020
1 parent 52798b3 commit 458d25f
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 99 deletions.
23 changes: 19 additions & 4 deletions src/components/datagrid/data_grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -761,13 +761,27 @@ export const EuiDataGrid: FunctionComponent<EuiDataGridProps> = (props) => {
};

// enables/disables grid controls based on available width
const [sizeIsStable, setSizeIsStable] = useState(false);

const [resizeRef, setResizeRef] = useState<HTMLDivElement | null>(null);
const gridDimensions = useResizeObserver(resizeRef);
useEffect(() => {
const { height, width } = gridDimensions;
setGridWidth(width);
setGridHeight(height);
}, [gridDimensions]);
if (resizeRef) {
if (sizeIsStable) {
const { height, width } = gridDimensions;
setGridWidth(width);
setGridHeight((currentHeight) => {
// because of a race condition between useResizeObserver which
// fires async outside of the React lifecycle
// and useEffect, we allow the height to grow but not shrink
return currentHeight < height ? height : currentHeight;
});
}
} else {
setGridWidth(0);
setGridHeight(0);
}
}, [sizeIsStable, resizeRef, gridDimensions]);

const hasRoomForGridControls = gridWidth > minSizeForControls || isFullScreen;

Expand Down Expand Up @@ -1112,6 +1126,7 @@ export const EuiDataGrid: FunctionComponent<EuiDataGridProps> = (props) => {
rowCount={rowCount}
interactiveCellId={interactiveCellId}
resetGridHeight={resetGridHeight}
setSizeIsStable={setSizeIsStable}
/>
</div>
</div>
Expand Down
40 changes: 28 additions & 12 deletions src/components/datagrid/data_grid_body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export interface EuiDataGridBodyProps {
setVisibleColumns: EuiDataGridHeaderRowProps['setVisibleColumns'];
switchColumnPos: EuiDataGridHeaderRowProps['switchColumnPos'];
resetGridHeight: () => void;
setSizeIsStable: (sizeIsStable: boolean) => void;
}

const defaultComparator: NonNullable<
Expand Down Expand Up @@ -116,8 +117,6 @@ const providedPopoverContents: EuiDataGridPopoverContents = {
},
};

const FOOTER_ROW_HEIGHT = 34;

const DefaultColumnFormatter: EuiDataGridPopoverContent = ({ children }) => {
return <EuiText>{children}</EuiText>;
};
Expand Down Expand Up @@ -291,18 +290,31 @@ export const EuiDataGridBody: FunctionComponent<EuiDataGridBodyProps> = (
handleHeaderMutation,
setVisibleColumns,
switchColumnPos,
resetGridHeight
resetGridHeight,
setSizeIsStable,
} = props;

const hasFooterRow = renderFooterCellValue;

const [headerRowRef, setHeaderRowRef] = useState<HTMLDivElement | null>(null);
const [footerRowRef, setFooterRowRef] = useState<HTMLDivElement | null>(null);

useMutationObserver(headerRowRef, handleHeaderMutation, {
subtree: true,
childList: true,
});
const { height: headerRowHeight } = useResizeObserver(headerRowRef, 'height');
const { height: footerRowHeight } = useResizeObserver(footerRowRef, 'height');

useEffect(() => resetGridHeight(), [headerRowHeight]);
useEffect(() => {
const isHeaderStable = headerRowHeight !== 0;
const isFooterStable = !hasFooterRow || footerRowHeight !== 0;
setSizeIsStable(isHeaderStable && isFooterStable);
}, [hasFooterRow, setSizeIsStable, headerRowHeight, footerRowHeight]);

useEffect(() => {
resetGridHeight();
}, [resetGridHeight, headerRowHeight, footerRowHeight]);

const startRow = pagination ? pagination.pageIndex * pagination.pageSize : 0;
let endRow = pagination
Expand Down Expand Up @@ -419,6 +431,7 @@ export const EuiDataGridBody: FunctionComponent<EuiDataGridBodyProps> = (
return (
<EuiDataGridFooterRow
key="footerRow"
ref={setFooterRowRef}
leadingControlColumns={leadingControlColumns}
trailingControlColumns={trailingControlColumns}
columns={columns}
Expand Down Expand Up @@ -508,6 +521,16 @@ export const EuiDataGridBody: FunctionComponent<EuiDataGridBodyProps> = (
if (gridRef.current) gridRef.current.resetAfterRowIndex(0);
}, [getRowHeight]);

const height =
// intentionally ignoring gridHeight if it is null/undefined/0
// and using it only if we have found the header&footer heights
(headerRowHeight && (!hasFooterRow || footerRowHeight) && gridHeight) ||
// otherwise compute the height
rowHeight * visibleRowIndices.length +
SCROLLBAR_HEIGHT +
headerRowHeight +
footerRowHeight;

return (
<DataGridHeaderRowHeightContext.Provider value={headerRowHeight}>
<Grid
Expand All @@ -521,14 +544,7 @@ export const EuiDataGridBody: FunctionComponent<EuiDataGridBodyProps> = (
}
width={gridWidth}
columnWidth={getWidth}
height={
// intentionally ignoring gridHeight if it is null/undefined/0
(headerRowHeight && gridHeight) ||
rowHeight * visibleRowIndices.length +
SCROLLBAR_HEIGHT +
headerRowHeight +
(footerRow ? FOOTER_ROW_HEIGHT : 0)
}
height={height}
rowHeight={getRowHeight}
itemData={{
setRowHeight,
Expand Down
3 changes: 1 addition & 2 deletions src/components/datagrid/data_grid_cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,7 @@ export class EuiDataGridCell extends Component<
className: classNames(cellClasses, this.state.cellProps.className),
};

const widthStyle = width != null ? { width: `${width}px` } : {};
cellProps.style = { ...style, widthStyle };
cellProps.style = { ...style, width };

const handleCellKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
if (isExpandable) {
Expand Down
170 changes: 89 additions & 81 deletions src/components/datagrid/data_grid_footer_row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import React, { FunctionComponent, HTMLAttributes, memo } from 'react';
import React, { forwardRef, HTMLAttributes, memo } from 'react';
import classnames from 'classnames';
import {
EuiDataGridControlColumn,
Expand Down Expand Up @@ -51,86 +51,47 @@ const DefaultColumnFormatter: EuiDataGridPopoverContent = ({ children }) => {
return <EuiText>{children}</EuiText>;
};

const EuiDataGridFooterRow: FunctionComponent<EuiDataGridFooterRowProps> = memo(
({
leadingControlColumns,
trailingControlColumns,
columns,
schema,
popoverContents,
columnWidths,
defaultColumnWidth,
className,
renderCellValue,
rowIndex,
interactiveCellId,
'data-test-subj': _dataTestSubj,
visibleRowIndex = rowIndex,
...rest
}) => {
const classes = classnames(
'euiDataGridRow',
'euiDataGridFooter',
className
);
const dataTestSubj = classnames('dataGridRow', _dataTestSubj);
const EuiDataGridFooterRow = memo(
forwardRef<HTMLDivElement, EuiDataGridFooterRowProps>(
(
{
leadingControlColumns,
trailingControlColumns,
columns,
schema,
popoverContents,
columnWidths,
defaultColumnWidth,
className,
renderCellValue,
rowIndex,
interactiveCellId,
'data-test-subj': _dataTestSubj,
visibleRowIndex = rowIndex,
...rest
},
ref
) => {
const classes = classnames(
'euiDataGridRow',
'euiDataGridFooter',
className
);
const dataTestSubj = classnames('dataGridRow', _dataTestSubj);

return (
<div
role="row"
className={classes}
data-test-subj={dataTestSubj}
{...rest}>
{leadingControlColumns.map(({ id, width }, i) => (
<EuiDataGridCell
key={`${id}-${rowIndex}`}
rowIndex={rowIndex}
visibleRowIndex={visibleRowIndex}
colIndex={i}
columnId={id}
popoverContent={DefaultColumnFormatter}
width={width}
renderCellValue={() => null}
interactiveCellId={interactiveCellId}
isExpandable={true}
className="euiDataGridFooterCell euiDataGridRowCell--controlColumn"
/>
))}
{columns.map(({ id }, i) => {
const columnType = schema[id] ? schema[id].columnType : null;
const popoverContent =
(columnType && popoverContents[columnType]) ||
DefaultColumnFormatter;

const width = columnWidths[id] || defaultColumnWidth;
const columnPosition = i + leadingControlColumns.length;

return (
return (
<div
ref={ref}
role="row"
className={classes}
data-test-subj={dataTestSubj}
{...rest}>
{leadingControlColumns.map(({ id, width }, i) => (
<EuiDataGridCell
key={`${id}-${rowIndex}`}
rowIndex={rowIndex}
visibleRowIndex={visibleRowIndex}
colIndex={columnPosition}
columnId={id}
columnType={columnType}
popoverContent={popoverContent}
width={width || undefined}
renderCellValue={renderCellValue}
interactiveCellId={interactiveCellId}
isExpandable={true}
className="euiDataGridFooterCell"
/>
);
})}
{trailingControlColumns.map(({ id, width }, i) => {
const colIndex = i + columns.length + leadingControlColumns.length;

return (
<EuiDataGridCell
key={`${id}-${rowIndex}`}
rowIndex={rowIndex}
visibleRowIndex={visibleRowIndex}
colIndex={colIndex}
colIndex={i}
columnId={id}
popoverContent={DefaultColumnFormatter}
width={width}
Expand All @@ -139,11 +100,58 @@ const EuiDataGridFooterRow: FunctionComponent<EuiDataGridFooterRowProps> = memo(
isExpandable={true}
className="euiDataGridFooterCell euiDataGridRowCell--controlColumn"
/>
);
})}
</div>
);
}
))}
{columns.map(({ id }, i) => {
const columnType = schema[id] ? schema[id].columnType : null;
const popoverContent =
(columnType && popoverContents[columnType]) ||
DefaultColumnFormatter;

const width = columnWidths[id] || defaultColumnWidth;
const columnPosition = i + leadingControlColumns.length;

return (
<EuiDataGridCell
key={`${id}-${rowIndex}`}
rowIndex={rowIndex}
visibleRowIndex={visibleRowIndex}
colIndex={columnPosition}
columnId={id}
columnType={columnType}
popoverContent={popoverContent}
width={width || undefined}
renderCellValue={renderCellValue}
interactiveCellId={interactiveCellId}
isExpandable={true}
className="euiDataGridFooterCell"
/>
);
})}
{trailingControlColumns.map(({ id, width }, i) => {
const colIndex = i + columns.length + leadingControlColumns.length;

return (
<EuiDataGridCell
key={`${id}-${rowIndex}`}
rowIndex={rowIndex}
visibleRowIndex={visibleRowIndex}
colIndex={colIndex}
columnId={id}
popoverContent={DefaultColumnFormatter}
width={width}
renderCellValue={() => null}
interactiveCellId={interactiveCellId}
isExpandable={true}
className="euiDataGridFooterCell euiDataGridRowCell--controlColumn"
/>
);
})}
</div>
);
}
)
);

EuiDataGridFooterRow.displayName = 'EuiDataGridFooterRow';

export { EuiDataGridFooterRow };

0 comments on commit 458d25f

Please sign in to comment.