Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 70 additions & 1 deletion packages/@react-spectrum/s2/stories/TableView.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import {
PickerItem,
Row,
StatusLight,
Tabs,
TabList,
Tab,
TableBody,
TableHeader,
TableView,
Expand All @@ -41,7 +44,7 @@ import FolderOpen from '../spectrum-illustrations/linear/FolderOpen';
import {Key} from '@react-types/shared';
import type {Meta, StoryObj} from '@storybook/react';
import React, {ReactElement, useCallback, useEffect, useRef, useState} from 'react';
import {SortDescriptor} from 'react-aria-components';
import {CollectionRendererContext, DefaultCollectionRenderer, SortDescriptor} from 'react-aria-components';
import {style} from '../style/spectrum-theme' with {type: 'macro'};
import {useAsyncList, useListData} from '@react-stately/data';
import {useEffectEvent} from '@react-aria/utils';
Expand Down Expand Up @@ -1714,3 +1717,69 @@ export const EditableTableWithAsyncSaving: StoryObj<EditableTableProps> = {
);
}
};

export const TableViewCollectionError: StoryObj<typeof DynamicTable> = {
render: function DynamicColumnsExample(args) {
const columns: Array<{
key: string;
label: string;
align?: 'start' | 'center' | 'end';
}> = [
{ key: 'name', label: 'Name'},
{ key: 'count', label: 'Count', align: 'end' },
];

interface DemoItem {
id: string;
name: string;
count: number;
}

const tabs = [
{ id: 'general', label: 'General' },
{ id: 'advanced', label: 'Advanced' },
{ id: 'about', label: 'About' },
];
const renderEmptyState = () => (
<CollectionRendererContext.Provider value={DefaultCollectionRenderer}>
{/* <Button>Sanity Check</Button> */}
<Tabs aria-label="Settings sections">
<TabList>
{tabs.map((tab) => (
<Tab key={tab.id} id={tab.id}>
{tab.label}
</Tab>
))}
</TabList>
</Tabs>
</CollectionRendererContext.Provider>
);

return (
<Content>
<TableView aria-label="Demo table" selectionMode="none" styles={style({ height: 320, minHeight: 240, minWidth: 320 })}>
<TableHeader>
{columns.map((column) => (
<Column
key={column.key}
align={column.align}
>
{column.label}
</Column>
))}
</TableHeader>
<TableBody<DemoItem>
items={[]}
renderEmptyState={renderEmptyState}>
</TableBody>
</TableView>
</Content>
);
},
args: Example.args,
parameters: {
docs: {
disable: true
}
}
}
41 changes: 41 additions & 0 deletions packages/@react-spectrum/s2/test/TableView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
TableView,
Text
} from '../src';
import {CollectionRendererContext, DefaultCollectionRenderer, Tab, TabList, Tabs} from 'react-aria-components';
import Filter from '../s2wf-icons/S2_Icon_Filter_20_N.svg';
import React from 'react';
import {User} from '@react-aria/test-utils';
Expand Down Expand Up @@ -108,4 +109,44 @@ describe('TableView', () => {
await tableTester.triggerColumnHeaderAction({column: 1, action: 0, interactionType: 'keyboard'});
expect(onAction).toHaveBeenCalledTimes(1);
});

it('should render empty state + nested collection without crashing', async () => {
const tabs = [
{id: 'general', label: 'General'},
{id: 'advanced', label: 'Advanced'}
];
const renderEmptyState = () => (
<Tabs aria-label="Settings">
<CollectionRendererContext.Provider value={DefaultCollectionRenderer}>
<TabList>
{tabs.map((tab) => (
<Tab key={tab.id} id={tab.id}>
{tab.label}
</Tab>
))}
</TabList>
</CollectionRendererContext.Provider>
</Tabs>
);

let renderResult: ReturnType<typeof render>;
await act(async () => {
renderResult = render(
<TableView aria-label="Debug table" selectionMode="none">
<TableHeader columns={columns}>
{(column) => (
<Column>
{column.name}
</Column>
)}
</TableHeader>
<TableBody items={[]} renderEmptyState={renderEmptyState} />
</TableView>
);
await Promise.resolve();
});
let {getAllByRole} = renderResult!;

expect(getAllByRole('tab')).toHaveLength(tabs.length);
});
});