diff --git a/packages/react-aria-components/docs/Table.mdx b/packages/react-aria-components/docs/Table.mdx
index a127ec94d90..f9323656ca1 100644
--- a/packages/react-aria-components/docs/Table.mdx
+++ b/packages/react-aria-components/docs/Table.mdx
@@ -225,7 +225,7 @@ HTML tables are meant for static content, rather than tables with rich interacti
`Table` helps achieve accessible and interactive table components that can be styled as needed.
* **Row selection** – Single or multiple selection, with optional checkboxes, disabled rows, and both `toggle` and `replace` selection behaviors.
-* **Columns** – Support for column sorting, [row header](https://www.w3.org/TR/wai-aria-1.1/#rowheader) columns, and nested column groups. Columns may optionally allow user resizing via mouse, touch, and keyboard interactions.
+* **Columns** – Support for column sorting and [row header](https://www.w3.org/TR/wai-aria-1.1/#rowheader) columns. Columns may optionally allow user resizing via mouse, touch, and keyboard interactions.
* **Interactive children** – Table cells may include interactive elements such as buttons, menus, etc.
* **Actions** – Rows and cells support optional actions such as navigation via click, tap, double click, or Enter key.
* **Async loading** – Support for loading and sorting items asynchronously.
@@ -239,7 +239,7 @@ HTML tables are meant for static content, rather than tables with rich interacti
-A table consists of a container element, with columns and rows of cells containing data inside. The cells within a table may contain focusable elements or plain text content. Columns may be nested to create column groups.
+A table consists of a container element, with columns and rows of cells containing data inside. The cells within a table may contain focusable elements or plain text content.
If the table supports row selection, each row can optionally include a selection checkbox. Additionally, a "select all" checkbox may be displayed in a column header if the table supports multiple row selection. A drag button may also be included within a cell if the row is draggable.
@@ -336,7 +336,7 @@ The following example includes a custom Column component with a sort indicator.
```tsx example export=true render=false
import type {ColumnProps} from 'react-aria-components';
-function MyColumn(props: ColumnProps) {
+function MyColumn(props: ColumnProps) {
return (
{({allowsSorting, sortDirection}) => <>
@@ -760,125 +760,6 @@ function AsyncSortTable() {
-## Nested columns
-
-Columns can be nested to create column groups. This will result in more than one header row to be created, with the `colspan`
-attribute of each column header cell set to the appropriate value so that the columns line up. Data for the leaf columns
-appears in each row of the table body.
-
-### Static
-
-This example also shows the use of the `isRowHeader` prop for `Column`, which controls which columns are included in the
-accessibility name for each row. By default, only the first column is included, but in some cases more than one column may
-be used to represent the row. In this example, the first and last name columns are combined to form the ARIA label for the row.
-Only leaf columns may be marked as row headers.
-
-```tsx example
-
-
-
- First Name
- Last Name
-
-
- Age
- Birthday
-
-
-
-
- | Sam |
- Smith |
- 36 |
- May 3 |
-
-
- | Julia |
- Jones |
- 24 |
- February 10 |
-
-
- | Peter |
- Parker |
- 28 |
- September 7 |
-
-
- | Bruce |
- Wayne |
- 32 |
- December 18 |
-
-
-
-```
-
-
- Show CSS
-
-```css
-.react-aria-Column {
- &[colspan] {
- text-align: center;
- }
-}
-```
-
-
-
-### Dynamic
-
-Nested columns can also be defined dynamically using the function syntax and the `childColumns` prop.
-The following example is the same as the example above, but defined dynamically.
-
-```tsx example
-interface ColumnDefinition {
- name: string,
- key: string,
- children?: ColumnDefinition[],
- isRowHeader?: boolean
-}
-
-let columns: ColumnDefinition[] = [
- {name: 'Name', key: 'name', children: [
- {name: 'First Name', key: 'first', isRowHeader: true},
- {name: 'Last Name', key: 'last', isRowHeader: true}
- ]},
- {name: 'Information', key: 'info', children: [
- {name: 'Age', key: 'age'},
- {name: 'Birthday', key: 'birthday'}
- ]}
-];
-
-let rows = [
- {id: 1, first: 'Sam', last: 'Smith', age: 36, birthday: 'May 3'},
- {id: 2, first: 'Julia', last: 'Jones', age: 24, birthday: 'February 10'},
- {id: 3, first: 'Peter', last: 'Parker', age: 28, birthday: 'September 7'},
- {id: 4, first: 'Bruce', last: 'Wayne', age: 32, birthday: 'December 18'}
-];
-
-
-
- {column => (
-
- {column.name}
-
- )}
-
-
- {item => (
-
- | {item.first} |
- {item.last} |
- {item.age} |
- {item.birthday} |
-
- )}
-
-
-```
-
## Empty state
Use the `renderEmptyState` prop to customize what the `TableBody` will display if there are no items.
@@ -1136,7 +1017,7 @@ This example shows how to create a reusable component that wraps `` to i
```tsx example export=true render=false
import {MenuTrigger, Button, Popover, Menu, MenuItem} from 'react-aria-components';
-interface ResizableTableColumnProps extends Omit, 'children'> {
+interface ResizableTableColumnProps extends Omit {
children: React.ReactNode
}
diff --git a/packages/react-aria-components/src/Table.tsx b/packages/react-aria-components/src/Table.tsx
index a3bf92a1444..d1d09787014 100644
--- a/packages/react-aria-components/src/Table.tsx
+++ b/packages/react-aria-components/src/Table.tsx
@@ -527,12 +527,8 @@ export interface ColumnRenderProps {
startResize(): void
}
-export interface ColumnProps extends RenderProps {
+export interface ColumnProps extends RenderProps {
id?: Key,
- /** Rendered contents of the column if `children` contains child columns. */
- title?: ReactNode,
- /** A list of child columns used when dynamically rendering nested child columns. */
- childColumns?: Iterable,
/** Whether the column allows sorting. */
allowsSorting?: boolean,
/** Whether a column is a [row header](https://www.w3.org/TR/wai-aria-1.1/#rowheader) and should be announced by assistive technology during row navigation. */
@@ -549,21 +545,9 @@ export interface ColumnProps extends RenderProps
maxWidth?: ColumnStaticSize | null
}
-function Column(props: ColumnProps, ref: ForwardedRef): JSX.Element | null {
- let render = useContext(CollectionRendererContext);
- let childColumns: ReactNode | ((item: T) => ReactNode);
- if (typeof render === 'function') {
- childColumns = render;
- } else if (typeof props.children !== 'function') {
- childColumns = props.children;
- }
-
- let children = useCollectionChildren({
- children: (props.title || props.childColumns) ? childColumns : null,
- items: props.childColumns
- });
+function Column(props: ColumnProps, ref: ForwardedRef): JSX.Element | null {
- return useSSRCollectionNode('column', props, ref, props.title ?? props.children, children);
+ return useSSRCollectionNode('column', props, ref, props.children);
}
/**
@@ -820,7 +804,7 @@ function TableColumnHeader({column}: {column: GridNode}) {
}
}
- let props: ColumnProps = column.props;
+ let props: ColumnProps = column.props;
let renderProps = useRenderProps({
...props,
id: undefined,
diff --git a/packages/react-aria-components/stories/index.stories.tsx b/packages/react-aria-components/stories/index.stories.tsx
index cd6cdc9101d..36c781edfee 100644
--- a/packages/react-aria-components/stories/index.stories.tsx
+++ b/packages/react-aria-components/stories/index.stories.tsx
@@ -874,7 +874,7 @@ export const TableDynamicExample = () => {
let rows = [
{id: 1, name: 'Games', date: '6/7/2020', type: 'File folder'},
- {id: 2, name: 'Program Files", date: "4/7/2021', type: 'File folder'},
+ {id: 2, name: 'Program Files', date: '4/7/2021', type: 'File folder'},
{id: 3, name: 'bootmgr', date: '11/20/2010', type: 'System file'},
{id: 4, name: 'log.txt', date: '1/18/20167', type: 'Text Document'}
];
diff --git a/packages/react-aria-components/test/Table.test.js b/packages/react-aria-components/test/Table.test.js
index 655b727008c..23f57e9323b 100644
--- a/packages/react-aria-components/test/Table.test.js
+++ b/packages/react-aria-components/test/Table.test.js
@@ -471,72 +471,6 @@ describe('Table', () => {
expect(columns[2]).not.toHaveTextContent('▲');
});
- it('should support nested column headers', async () => {
- let columns = [
- {name: 'Name', key: 'name', children: [
- {name: 'First Name', key: 'first', isRowHeader: true},
- {name: 'Last Name', key: 'last', isRowHeader: true}
- ]},
- {name: 'Information', key: 'info', children: [
- {name: 'Age', key: 'age'},
- {name: 'Birthday', key: 'birthday'}
- ]}
- ];
-
- let leafColumns = [{key: 'first'}, {key: 'last'}, {key: 'age'}, {key: 'birthday'}];
-
- let items = [
- {id: 1, first: 'Sam', last: 'Smith', age: 36, birthday: 'May 3'},
- {id: 2, first: 'Julia', last: 'Jones', age: 24, birthday: 'February 10'},
- {id: 3, first: 'Peter', last: 'Parker', age: 28, birthday: 'September 7'},
- {id: 4, first: 'Bruce', last: 'Wayne', age: 32, birthday: 'December 18'}
- ];
-
- let {getAllByRole} = render(
-
- );
-
- let header = getAllByRole('rowgroup')[0];
- let rows = within(header).getAllByRole('row');
- expect(rows).toHaveLength(2);
-
- let cells = within(rows[0]).getAllByRole('columnheader');
- expect(cells).toHaveLength(2);
- expect(cells[0]).toHaveAttribute('aria-colspan', '2');
- expect(cells[1]).toHaveAttribute('aria-colspan', '2');
-
- await user.tab();
- fireEvent.keyDown(document.activeElement, {key: 'ArrowUp'});
- fireEvent.keyUp(document.activeElement, {key: 'ArrowUp'});
-
- cells = within(rows[1]).getAllByRole('columnheader');
- expect(document.activeElement).toBe(cells[0]);
-
- fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'});
- fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'});
- expect(document.activeElement).toBe(cells[1]);
-
- fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'});
- fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'});
- expect(document.activeElement).toBe(cells[2]);
-
- fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'});
- fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'});
- expect(document.activeElement).toBe(cells[3]);
-
- fireEvent.keyDown(document.activeElement, {key: 'ArrowUp'});
- fireEvent.keyUp(document.activeElement, {key: 'ArrowUp'});
- cells = within(rows[0]).getAllByRole('columnheader');
- expect(document.activeElement).toBe(cells[1]);
-
- fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'});
- fireEvent.keyUp(document.activeElement, {key: 'ArrowLeft'});
- expect(document.activeElement).toBe(cells[0]);
- });
-
it('should support empty state', () => {
let {getAllByRole, getByRole} = render(