From f0afa75ca7fb0bd5ada5111014ab0e5c84d1d086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Vyhn=C3=A1lek?= Date: Tue, 22 Aug 2023 12:45:13 +0200 Subject: [PATCH 1/8] Table/DataGrid: fix visuals for overflow --- ...-1a06bc91-0c0f-464f-a1c3-4523427d45a1.json | 7 ++ .../components/Table/useTableStyles.styles.ts | 1 + .../src/hooks/useTableColumnSizing.tsx | 4 +- .../stories/DataGrid/Default.stories.tsx | 44 ++++---- .../DataGrid/ResizableColumns.stories.tsx | 82 +++++++------- .../ResizableColumnsControlled.stories.tsx | 78 ++++++------- .../ResizableColumnsUncontrolled.stories.tsx | 106 +++++++++--------- 7 files changed, 170 insertions(+), 152 deletions(-) create mode 100644 change/@fluentui-react-table-1a06bc91-0c0f-464f-a1c3-4523427d45a1.json diff --git a/change/@fluentui-react-table-1a06bc91-0c0f-464f-a1c3-4523427d45a1.json b/change/@fluentui-react-table-1a06bc91-0c0f-464f-a1c3-4523427d45a1.json new file mode 100644 index 00000000000000..e5b367f414a594 --- /dev/null +++ b/change/@fluentui-react-table-1a06bc91-0c0f-464f-a1c3-4523427d45a1.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "fix: Improve visuals when Table/DataGrid overflows it's parent", + "packageName": "@fluentui/react-table", + "email": "jirivyhnalek@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-components/react-table/src/components/Table/useTableStyles.styles.ts b/packages/react-components/react-table/src/components/Table/useTableStyles.styles.ts index aeb34e0edbae9c..ec91ca41e46350 100644 --- a/packages/react-components/react-table/src/components/Table/useTableStyles.styles.ts +++ b/packages/react-components/react-table/src/components/Table/useTableStyles.styles.ts @@ -20,6 +20,7 @@ const useTableLayoutStyles = makeStyles({ const useFlexLayoutStyles = makeStyles({ root: { display: 'block', + minWidth: 'fit-content', }, }); diff --git a/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx b/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx index 2c1a3cfe3e120c..4722f3b5e90724 100644 --- a/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx +++ b/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx @@ -77,14 +77,16 @@ function useTableColumnSizingState( getColumnWidths: columnResizeState.getColumns, getTableHeaderCellProps: (columnId: TableColumnId) => { const col = columnResizeState.getColumnById(columnId); + const isLastColumn = columns[columns.length - 1]?.columnId === columnId; - const aside = ( + const aside = isLastColumn ? null : ( ); + return col ? { style: getColumnStyles(col), diff --git a/packages/react-components/react-table/stories/DataGrid/Default.stories.tsx b/packages/react-components/react-table/stories/DataGrid/Default.stories.tsx index ff9a21626a279c..6f64095ba677d8 100644 --- a/packages/react-components/react-table/stories/DataGrid/Default.stories.tsx +++ b/packages/react-components/react-table/stories/DataGrid/Default.stories.tsx @@ -150,27 +150,29 @@ const columns: TableColumnDefinition[] = [ export const Default = () => { return ( - item.file.label} - onSelectionChange={(e, data) => console.log(data)} - focusMode="composite" - > - - - {({ renderHeaderCell }) => {renderHeaderCell()}} - - - > - {({ item, rowId }) => ( - key={rowId} selectionCell={{ 'aria-label': 'Select row' }}> - {({ renderCell }) => {renderCell(item)}} +
+ item.file.label} + onSelectionChange={(e, data) => console.log(data)} + focusMode="composite" + > + + + {({ renderHeaderCell }) => {renderHeaderCell()}} - )} - - + + > + {({ item, rowId }) => ( + key={rowId} selectionCell={{ 'aria-label': 'Select row' }}> + {({ renderCell }) => {renderCell(item)}} + + )} + + +
); }; diff --git a/packages/react-components/react-table/stories/DataGrid/ResizableColumns.stories.tsx b/packages/react-components/react-table/stories/DataGrid/ResizableColumns.stories.tsx index 94df950d89f9b9..a9c0f19313329c 100644 --- a/packages/react-components/react-table/stories/DataGrid/ResizableColumns.stories.tsx +++ b/packages/react-components/react-table/stories/DataGrid/ResizableColumns.stories.tsx @@ -178,47 +178,49 @@ export const ResizableColumns = () => { const refMap = React.useRef>({}); return ( - item.file.label} - selectionMode="multiselect" - resizableColumns - columnSizingOptions={columnSizingOptions} - > - - - {({ renderHeaderCell, columnId }, dataGrid) => - dataGrid.resizableColumns ? ( - - - (refMap.current[columnId] = el)}> - {renderHeaderCell()} - - - - - - Keyboard Column Resizing - - - - - ) : ( - {renderHeaderCell()} - ) - } - - - > - {({ item, rowId }) => ( - key={rowId} selectionCell={{ 'aria-label': 'Select row' }}> - {({ renderCell }) => {renderCell(item)}} +
+ item.file.label} + selectionMode="multiselect" + resizableColumns + columnSizingOptions={columnSizingOptions} + > + + + {({ renderHeaderCell, columnId }, dataGrid) => + dataGrid.resizableColumns ? ( + + + (refMap.current[columnId] = el)}> + {renderHeaderCell()} + + + + + + Keyboard Column Resizing + + + + + ) : ( + {renderHeaderCell()} + ) + } - )} - - + + > + {({ item, rowId }) => ( + key={rowId} selectionCell={{ 'aria-label': 'Select row' }}> + {({ renderCell }) => {renderCell(item)}} + + )} + + +
); }; diff --git a/packages/react-components/react-table/stories/Table/ResizableColumnsControlled.stories.tsx b/packages/react-components/react-table/stories/Table/ResizableColumnsControlled.stories.tsx index 7661bd6657680f..63de8b5dc8d90e 100644 --- a/packages/react-components/react-table/stories/Table/ResizableColumnsControlled.stories.tsx +++ b/packages/react-components/react-table/stories/Table/ResizableColumnsControlled.stories.tsx @@ -272,46 +272,48 @@ export const ResizableColumnsControlled = () => { Add removed column

- - - - {columns.map((column, index) => ( - - - - {column.renderHeaderCell()} - removeColumn(index)}> - x - - - - - - - Keyboard Column Resizing - - - - - ))} - - - - {rows.map(({ item }) => ( - - {columns.map(column => ( - - {column.renderCell(item)} - +
+
+ + + {columns.map((column, index) => ( + + + + {column.renderHeaderCell()} + removeColumn(index)}> + x + + + + + + + Keyboard Column Resizing + + + + ))} - ))} - -
+ + + {rows.map(({ item }) => ( + + {columns.map(column => ( + + {column.renderCell(item)} + + ))} + + ))} + + + ); }; diff --git a/packages/react-components/react-table/stories/Table/ResizableColumnsUncontrolled.stories.tsx b/packages/react-components/react-table/stories/Table/ResizableColumnsUncontrolled.stories.tsx index db34111c955683..eabfa389a25aaa 100644 --- a/packages/react-components/react-table/stories/Table/ResizableColumnsUncontrolled.stories.tsx +++ b/packages/react-components/react-table/stories/Table/ResizableColumnsUncontrolled.stories.tsx @@ -161,60 +161,62 @@ export const ResizableColumnsUncontrolled = () => {

- - - - {columns.map(column => ( - - - +
+ + + {columns.map(column => ( + + + + {column.renderHeaderCell()} + + + + + + Keyboard Column Resizing + + + + + ))} + + + + {rows.map(({ item }) => ( + + + + {item.file.label} + + + + + } > - {column.renderHeaderCell()} - - - - - - Keyboard Column Resizing - - - - + {item.author.label} + + + + {item.lastUpdated.label} + + + + {item.lastUpdate.label} + + + ))} - - - - {rows.map(({ item }) => ( - - - - {item.file.label} - - - - - } - > - {item.author.label} - - - - {item.lastUpdated.label} - - - - {item.lastUpdate.label} - - - - ))} - -
+ + + ); }; From 3cc1511382a26c7a034a821eb7ffdb3e6877dd6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Vyhn=C3=A1lek?= Date: Tue, 22 Aug 2023 16:05:52 +0200 Subject: [PATCH 2/8] only use fit-content for resizable columns --- .../src/stories/Table.stories.tsx | 135 +++++++++++++++++- .../src/components/DataGrid/useDataGrid.ts | 1 + .../components/Table/useTableStyles.styles.ts | 1 - .../react-table/src/hooks/types.ts | 4 +- .../src/hooks/useTableColumnSizing.tsx | 9 ++ 5 files changed, 147 insertions(+), 3 deletions(-) diff --git a/apps/vr-tests-react-components/src/stories/Table.stories.tsx b/apps/vr-tests-react-components/src/stories/Table.stories.tsx index a4141467d2a5e1..fae847ea6f42c6 100644 --- a/apps/vr-tests-react-components/src/stories/Table.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Table.stories.tsx @@ -23,12 +23,43 @@ import { TableCellActions, TableProps, TableRowProps, + useTableColumnSizing_unstable, + useTableFeatures, + TableColumnDefinition, + createTableColumn, } from '@fluentui/react-table'; import { Button } from '@fluentui/react-button'; import { storiesOf } from '@storybook/react'; import { Steps, StoryWright } from 'storywright'; -const items = [ +type FileCell = { + label: string; + icon: JSX.Element; +}; + +type LastUpdatedCell = { + label: string; + timestamp: number; +}; + +type LastUpdateCell = { + label: string; + icon: JSX.Element; +}; + +type AuthorCell = { + label: string; + status: PresenceBadgeStatus; +}; + +type Item = { + file: FileCell; + author: AuthorCell; + lastUpdated: LastUpdatedCell; + lastUpdate: LastUpdateCell; +}; + +const items: Item[] = [ { file: { label: 'Meeting notes', icon: }, author: { label: 'Max Mustermann', status: 'available' }, @@ -74,6 +105,25 @@ const columns = [ { columnKey: 'lastUpdate', label: 'Last update' }, ]; +const columnsDef: TableColumnDefinition[] = [ + createTableColumn({ + columnId: 'file', + renderHeaderCell: () => <>File, + }), + createTableColumn({ + columnId: 'author', + renderHeaderCell: () => <>Author, + }), + createTableColumn({ + columnId: 'lastUpdated', + renderHeaderCell: () => <>Last updated, + }), + createTableColumn({ + columnId: 'lastUpdate', + renderHeaderCell: () => <>Last update, + }), +]; + interface SharedVrTestArgs { noNativeElements: TableProps['noNativeElements']; selectedRowAppearance?: TableRowProps['appearance']; @@ -634,6 +684,85 @@ const Truncate: React.FC = ({ noNativ ); +const ResizableColumns: React.FC = ({ + noNativeElements, + scrollToEnd, +}) => { + const [columnSizingOptions] = React.useState({ + file: { + idealWidth: 300, + minWidth: 300, + }, + }); + + const { columnSizing_unstable: columnSizing, tableRef } = useTableFeatures( + { + columns: columnsDef, + items, + }, + [ + useTableColumnSizing_unstable({ + columnSizingOptions, + }), + ], + ); + return ( +
+ + + + {columns.map(column => ( + + {column.label} + + ))} + + + + {items.map((item, i) => ( + + + + {item.file.label} + +
+
+ ); +}; + ([true, false] as const).forEach(noNativeElements => { const layoutName = noNativeElements ? 'flex' : 'table'; storiesOf(`Table layout ${layoutName} - cell actions`, module) @@ -760,4 +889,8 @@ const Truncate: React.FC = ({ noNativ .addStory('default (disabled)', () => ) .addStory('false', () => ) .addStory('true', () => ); + + storiesOf(`Table layout ${layoutName} - resizable columns`, module) + .addStory('default', () => ) + .addStory('end', () => ); }); diff --git a/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts b/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts index 039d058be6bacd..5b9b5f59a92dca 100644 --- a/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts +++ b/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts @@ -110,6 +110,7 @@ export const useDataGrid_unstable = (props: DataGridProps, ref: React.Ref; export type ColumnSizingTableHeaderCellProps = Pick; export type ColumnSizingTableCellProps = Pick; @@ -184,6 +185,7 @@ export interface TableColumnSizingState { getOnMouseDown: (columnId: TableColumnId) => (e: React.MouseEvent | React.TouchEvent) => void; setColumnWidth: (columnId: TableColumnId, newSize: number) => void; getColumnWidths: () => ColumnWidthState[]; + getTableProps: (props?: Partial) => ColumnSizingTableProps; getTableHeaderCellProps: (columnId: TableColumnId) => ColumnSizingTableHeaderCellProps; getTableCellProps: (columnId: TableColumnId) => ColumnSizingTableCellProps; enableKeyboardMode: ( diff --git a/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx b/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx index 4722f3b5e90724..68d3c9b8f618a7 100644 --- a/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx +++ b/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx @@ -75,6 +75,15 @@ function useTableColumnSizingState( setColumnWidth: (columnId: TableColumnId, w: number) => columnResizeState.setColumnWidth(undefined, { columnId, width: w }), getColumnWidths: columnResizeState.getColumns, + getTableProps: (props = {}) => { + return { + ...props, + style: { + minWidth: 'fit-content', + ...(props.style || {}), + }, + }; + }, getTableHeaderCellProps: (columnId: TableColumnId) => { const col = columnResizeState.getColumnById(columnId); const isLastColumn = columns[columns.length - 1]?.columnId === columnId; From 1e674c3e6dfdcc8211b41e2911e6d2f317ca080d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Vyhn=C3=A1lek?= Date: Tue, 22 Aug 2023 16:07:25 +0200 Subject: [PATCH 3/8] props order --- .../react-table/src/components/DataGrid/useDataGrid.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts b/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts index 5b9b5f59a92dca..acf991ca4359f6 100644 --- a/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts +++ b/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts @@ -110,9 +110,9 @@ export const useDataGrid_unstable = (props: DataGridProps, ref: React.Ref Date: Tue, 22 Aug 2023 16:11:46 +0200 Subject: [PATCH 4/8] fix storybook examples --- .../stories/DataGrid/Default.stories.tsx | 44 +++++++++---------- .../ResizableColumnsControlled.stories.tsx | 2 +- .../ResizableColumnsUncontrolled.stories.tsx | 2 +- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/packages/react-components/react-table/stories/DataGrid/Default.stories.tsx b/packages/react-components/react-table/stories/DataGrid/Default.stories.tsx index 6f64095ba677d8..ff9a21626a279c 100644 --- a/packages/react-components/react-table/stories/DataGrid/Default.stories.tsx +++ b/packages/react-components/react-table/stories/DataGrid/Default.stories.tsx @@ -150,29 +150,27 @@ const columns: TableColumnDefinition[] = [ export const Default = () => { return ( -
- item.file.label} - onSelectionChange={(e, data) => console.log(data)} - focusMode="composite" - > - - - {({ renderHeaderCell }) => {renderHeaderCell()}} + item.file.label} + onSelectionChange={(e, data) => console.log(data)} + focusMode="composite" + > + + + {({ renderHeaderCell }) => {renderHeaderCell()}} + + + > + {({ item, rowId }) => ( + key={rowId} selectionCell={{ 'aria-label': 'Select row' }}> + {({ renderCell }) => {renderCell(item)}} - - > - {({ item, rowId }) => ( - key={rowId} selectionCell={{ 'aria-label': 'Select row' }}> - {({ renderCell }) => {renderCell(item)}} - - )} - - -
+ )} + +
); }; diff --git a/packages/react-components/react-table/stories/Table/ResizableColumnsControlled.stories.tsx b/packages/react-components/react-table/stories/Table/ResizableColumnsControlled.stories.tsx index 63de8b5dc8d90e..5fda7f533f0628 100644 --- a/packages/react-components/react-table/stories/Table/ResizableColumnsControlled.stories.tsx +++ b/packages/react-components/react-table/stories/Table/ResizableColumnsControlled.stories.tsx @@ -273,7 +273,7 @@ export const ResizableColumnsControlled = () => {

- +
{columns.map((column, index) => ( diff --git a/packages/react-components/react-table/stories/Table/ResizableColumnsUncontrolled.stories.tsx b/packages/react-components/react-table/stories/Table/ResizableColumnsUncontrolled.stories.tsx index eabfa389a25aaa..03416a45201829 100644 --- a/packages/react-components/react-table/stories/Table/ResizableColumnsUncontrolled.stories.tsx +++ b/packages/react-components/react-table/stories/Table/ResizableColumnsUncontrolled.stories.tsx @@ -162,7 +162,7 @@ export const ResizableColumnsUncontrolled = () => {

-
+
{columns.map(column => ( From 2e9c2fdf73088517df135f9f6229cc4801b21aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Vyhn=C3=A1lek?= Date: Tue, 22 Aug 2023 16:57:38 +0200 Subject: [PATCH 5/8] formatting --- apps/vr-tests-react-components/src/stories/Table.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vr-tests-react-components/src/stories/Table.stories.tsx b/apps/vr-tests-react-components/src/stories/Table.stories.tsx index fae847ea6f42c6..b82e744b24a17a 100644 --- a/apps/vr-tests-react-components/src/stories/Table.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Table.stories.tsx @@ -754,7 +754,7 @@ const ResizableColumns: React.FC = el.scrollIntoView(); } }} - /> + /> ))} From dfe5a74dde264cdfcd89368124dd8e5603c8cb05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Vyhn=C3=A1lek?= Date: Tue, 22 Aug 2023 17:22:25 +0200 Subject: [PATCH 6/8] fix missing default state --- .../react-table/src/hooks/useTableColumnSizing.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx b/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx index 68d3c9b8f618a7..1f63ef74d398ed 100644 --- a/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx +++ b/packages/react-components/react-table/src/hooks/useTableColumnSizing.tsx @@ -18,6 +18,7 @@ export const defaultColumnSizingState: TableColumnSizingState = { getColumnWidths: () => [], getOnMouseDown: () => () => null, setColumnWidth: () => null, + getTableProps: () => ({}), getTableHeaderCellProps: () => ({ style: {}, columnId: '' }), getTableCellProps: () => ({ style: {}, columnId: '' }), enableKeyboardMode: () => () => null, From a26d800f41af0b8460f77055846a0de0f998f850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Vyhn=C3=A1lek?= Date: Wed, 23 Aug 2023 09:51:07 +0200 Subject: [PATCH 7/8] fix unit tests --- .../react-table/src/hooks/useTableColumnSizing.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-components/react-table/src/hooks/useTableColumnSizing.test.ts b/packages/react-components/react-table/src/hooks/useTableColumnSizing.test.ts index 66502b4399c78c..7f3669171bce08 100644 --- a/packages/react-components/react-table/src/hooks/useTableColumnSizing.test.ts +++ b/packages/react-components/react-table/src/hooks/useTableColumnSizing.test.ts @@ -62,6 +62,7 @@ describe('useTableColumnSizing', () => { "getOnMouseDown": [MockFunction], "getTableCellProps": [Function], "getTableHeaderCellProps": [Function], + "getTableProps": [Function], "setColumnWidth": [Function], } `); From e3d9aceac48cf491a2d85ffa80c9fec25d54b44a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Vyhn=C3=A1lek?= Date: Thu, 24 Aug 2023 10:35:28 +0200 Subject: [PATCH 8/8] dashed border in vr test --- apps/vr-tests-react-components/src/stories/Table.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vr-tests-react-components/src/stories/Table.stories.tsx b/apps/vr-tests-react-components/src/stories/Table.stories.tsx index b82e744b24a17a..17d5238e7e2c9e 100644 --- a/apps/vr-tests-react-components/src/stories/Table.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Table.stories.tsx @@ -707,7 +707,7 @@ const ResizableColumns: React.FC = ], ); return ( -
+