diff --git a/packages/eui/changelogs/upcoming/8082.md b/packages/eui/changelogs/upcoming/8082.md new file mode 100644 index 00000000000..2d7ec615eac --- /dev/null +++ b/packages/eui/changelogs/upcoming/8082.md @@ -0,0 +1,3 @@ +**Bug fixes** + +- Fixed an `EuiDataGrid` regression from [#8015](https://github.com/elastic/eui/pull/8015) to allow `onColumnResize` to control columns' `initialWidth`s again diff --git a/packages/eui/src/components/datagrid/data_grid_types.ts b/packages/eui/src/components/datagrid/data_grid_types.ts index f92e673cbb7..4bd75cfa4cf 100644 --- a/packages/eui/src/components/datagrid/data_grid_types.ts +++ b/packages/eui/src/components/datagrid/data_grid_types.ts @@ -349,6 +349,10 @@ export type CommonGridProps = CommonProps & sorting?: EuiDataGridSorting; /** * A callback for when a column's size changes. Callback receives `{ columnId: string, width: number }`. + * + * When an `onColumnResize` function is passed, `columns[].initialWidth` behaves like a + * controlled (rather than uncontrolled) prop, and can be used to completely manage column + * widths even after initial mount. */ onColumnResize?: EuiDataGridOnColumnResizeHandler; /** diff --git a/packages/eui/src/components/datagrid/utils/col_widths.test.ts b/packages/eui/src/components/datagrid/utils/col_widths.test.ts index c98741d3ce1..ee4cf604f39 100644 --- a/packages/eui/src/components/datagrid/utils/col_widths.test.ts +++ b/packages/eui/src/components/datagrid/utils/col_widths.test.ts @@ -88,7 +88,6 @@ describe('useColumnWidths', () => { columns: [{ id: 'b', initialWidth: 75 }, { id: 'c' }], trailingControlColumns: [{ id: 'd', width: 25 }] as any, defaultColumnWidth: 150, - onColumnResize: jest.fn(), }; describe('columnWidths', () => { @@ -136,16 +135,36 @@ describe('useColumnWidths', () => { }); expect(result.current.columnWidths).toEqual({ b: 150 }); }); + + it('does override user resized column widths if `onColumnResize` is passed', () => { + const controlledWidthsArgs = { + ...args, + onColumnResize: jest.fn(), + }; + const { rerender, result } = renderHook(useColumnWidths, { + initialProps: controlledWidthsArgs, + }); + + renderHookAct(() => result.current.setColumnWidth('b', 150)); + rerender({ + ...controlledWidthsArgs, + columns: [{ id: 'b', initialWidth: 100 }], + }); + expect(result.current.columnWidths).toEqual({ b: 100 }); + }); }); }); describe('setColumnWidth', () => { it("sets a single column's width in the columnWidths map", () => { - const { result } = renderHook(() => useColumnWidths(args)); + const onColumnResize = jest.fn(); + const { result } = renderHook(() => + useColumnWidths({ ...args, onColumnResize }) + ); renderHookAct(() => result.current.setColumnWidth('c', 125)); expect(result.current.columnWidths).toEqual({ b: 75, c: 125 }); - expect(args.onColumnResize).toHaveBeenCalledWith({ + expect(onColumnResize).toHaveBeenCalledWith({ columnId: 'c', width: 125, }); diff --git a/packages/eui/src/components/datagrid/utils/col_widths.ts b/packages/eui/src/components/datagrid/utils/col_widths.ts index e919151143e..d42b3b176c4 100644 --- a/packages/eui/src/components/datagrid/utils/col_widths.ts +++ b/packages/eui/src/components/datagrid/utils/col_widths.ts @@ -79,19 +79,25 @@ export const useColumnWidths = ({ setColumnWidth: (columnId: string, width: number) => void; getColumnWidth: (index: number) => number; } => { + const hasOnColumnResize = !!onColumnResize; const getInitialWidths = useCallback( (prevColumnWidths?: EuiDataGridColumnWidths) => { const columnWidths = { ...prevColumnWidths }; columns .filter(doesColumnHaveAnInitialWidth) .forEach(({ id, initialWidth }) => { - if (columnWidths[id] == null) { + // Several Kibana datagrids are using `onColumnResize` and `column.initialWidth` + // to fully control column widths. Sadly, we didn't do a good job documenting + // the intent of this prop and how controlled it is, so for now we'll assume + // that any datagrid passing `onColumnResize` is controlling its column widths + // and should override any internal column width state set by user resizing + if (hasOnColumnResize || columnWidths[id] == null) { columnWidths[id] = initialWidth!; } }); return columnWidths; }, - [columns] + [columns, hasOnColumnResize] ); // Passes initializer function for performance, so computing only runs once on init