rfcs/2022-v3-resizable-columns.md
Being able to resize columns in TableView is a highly requested feature. This feature is common in table components. This RFC proposes how to make columns resizable in TableView.
This feature bas been heavily requested by Adobe Analytics Workspace customers. Being able to resize columns is a feature that users expect when they interact with tables. Column resizing also makes the table content more usable because if content is truncated, the user can resize the column so that it's no longer truncated.
Column resizing will be added to the TableView. It will involve updates to TableView, TableLayout and useTableState. We will also need to add the following components/hooks:
Individual columns can be set to allow resizing by adding the allowsResizing prop to the <Column> component.
The defaultWidth prop is used on the <Column> component to set the width for uncontrolled column resizing. defaultWidth supports pixel values (ex. defaultWidth=500), percentage values (ex. defualtWidth='50%') and fractional units like css grid (ex. defaultWidth='1fr').
The minWidth and maxWidth props are used on the <Column> component to define the minimum and maximum allowed column widths respectively. These props support pixel values and percentages.
The onColumnResizeand onColumnResizeEnd props can be added to the <TableView> component. onColumnResize will call the onResize callback whenever columns are resized by the user, passing in an array of all the columns that were affected by the resize. onColumnResizeEnd is the same as onColumnResize but only get's called when done resizing.
<TableView width={800} onColumnResize={onResize} onColumnResizeEnd={onResizeEnd}>
<TableHeader>
<Column allowsResizing defaultWidth={200} minWidth={175}>File Name</Column>
<Column allowsResizing defaultWidth="1fr" maxWidth={500}>Size</Column>
<Column allowsResizing defaultWidth="20%">Type</Column>
</TableHeader>
...
</TableView>
Code sandbox used to develop the resize alogrithm and test it: https://codesandbox.io/s/column-width-resizer-final-jo4rr?file=/src/column-utils.spec.js
Codepen demo of the resize alogrithm: https://codepen.io/mpeterson/pen/PoJpJvK
Columns get bucketed into two different categories when resizing. These buckets are static columns and dynamic columns. Static columns do not change size unless the user explicitly resizes them. Dynamic columns can change size when columns around them are resized as well as when they are explicitly resized by the user.
Static columns are any column where the defaultWidth is set to a pixel value or a percentage. If a user manually resizes a column, this will also convert it to static.
Dynamic columns are any column where the defaultWidth is not set or if the defaultWidth is set to a fractional unit.
Users can only resize within the bounds of the min and max for that column.
Column limits default to a min of 75 and a max of infinity unless a different value is provided by the dev using minWidth and maxWidth.
Resizing a column will only affect the dynamic columns that come after that column (to the right in left to right layouts).
Calculating column widths follows this flow:
defaultWidth is provided, the column defaults to 1fr.return/enter or space will activate a dropdownreturn/enter or space on the dropdown item will activate the resize mode, closing the dropdown and focussing the resizerEsc will exit resize mode and return focus to the column headerTab will also exit resize mode and tab out of the table entirelyShift + Tab, the column header will be focussedStories will be added to the storybook for column resizing. The react spectrum documentation will also be updated to add the new props and show examples of how to setup column resizing
There may be minor performance hits from adding resizing. This adds to the amount of calculation that happens each time the table renders.
The a11y proposal involves changing the default behavior for clicking on a table column header if it is sortable and resizable. Currently clicking on a column header that is sortable will toggle the sort. If it is resizable and sortable, clicking on the column header will activate a dropdown where the user can select to sort or resize. This is an extra click for the end user.
There shouldn't be any breaking changes with this feature addition.
The only change in existing behavior is the change to table header click behavior if something is both sortable and resizable. Currently clicking on a column header that is sortable will toggle the sort. If it is resizable and sortable, clicking on the column header will activate a dropdown where the user can select to sort or resize. This is an extra click for the end user.
We researched many commonly used tables components to help define the desired behavior for this column resizing feature. Three main examples that we researched were Excel, Marketo Engage and AG Grid.
Still need to define how a controlled model will work for column resizing.