Skip to content

Commit 2d86523

Browse files
authored
Make SkeletonTable modular (#352)
* feat(skeleton): Refactor SkeletonTable to be modular * feat(skeleton): Add new SkeletonTable docs * feat(skeleton): Enhance cypress tests
1 parent 6b8cf86 commit 2d86523

29 files changed

+1151
-265
lines changed

cypress/component/SkeletonTable.cy.tsx

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,73 @@
11
import React from 'react';
2-
import { Th } from '@patternfly/react-table';
3-
import SkeletonTable from '../../packages/module/dist/dynamic/SkeletonTable';
2+
import { RowSelectVariant } from '@patternfly/react-table';
3+
import SkeletonTable from '@patternfly/react-component-groups/dist/dynamic/SkeletonTable';
44

55
describe('SkeletonTable', () => {
66
beforeEach(() => {
77
cy.viewport(1600, 800);
88
});
99

1010
it('renders SkeletonTable', () => {
11-
const SkeletonTableExample = <SkeletonTable rows={10} columns={[ 'first', 'second' ]} />;
11+
const SkeletonTableExample = <SkeletonTable rowsCount={10} columns={[ 'First', 'Second' ]} />;
1212
cy.mount(SkeletonTableExample);
1313
cy.get('table').should('exist');
14-
cy.get('table thead tr').should('have.text', 'firstsecond');
14+
cy.get('table thead tr th').eq(0).should('have.text', 'First');
15+
cy.get('table thead tr th').eq(1).should('have.text', 'Second');
1516
});
1617

1718
it ('can be used without passing columns', () => {
18-
const SkeletonTableExample = <SkeletonTable rows={10} numberOfColumns={2} />;
19+
const SkeletonTableExample = <SkeletonTable rowsCount={10} columnsCount={2} />;
1920
cy.mount(SkeletonTableExample);
2021
cy.get('table').should('exist');
2122
cy.get('table thead tr').should('have.text', '');
2223
});
2324

2425
it('contains checkboxes when passed isSelectable', () => {
25-
const SkeletonTableExample = <SkeletonTable rows={10} columns={[ 'first', 'second' ]} isSelectable />;
26+
const SkeletonTableExample = <SkeletonTable rowsCount={10} columns={[ 'First', 'Second' ]} isSelectable />;
2627
cy.mount(SkeletonTableExample);
2728
cy.get('table').should('exist');
28-
cy.get('table thead tr').should('have.text', 'firstsecond');
29+
cy.get('table thead tr th').eq(0).should('have.text', 'Data selection table header cell');
30+
cy.get('table thead tr th').eq(1).should('have.text', 'First');
31+
cy.get('table thead tr th').eq(2).should('have.text', 'Second');
2932
cy.get('input[type="checkbox"]').should('have.length', 10);
3033
});
3134

3235
it('is expandable when passed isExpandable', () => {
33-
const SkeletonTableExample = <SkeletonTable rows={10} columns={[ 'first', 'second' ]} isExpandable />;
36+
const SkeletonTableExample = <SkeletonTable rowsCount={10} columns={[ 'First', 'Second' ]} isExpandable />;
3437
cy.mount(SkeletonTableExample);
3538
cy.get('table').should('exist');
36-
cy.get('table thead tr').should('have.text', 'firstsecond');
39+
cy.get('table thead tr th').eq(0).should('have.text', 'Data expansion table header cell');
40+
cy.get('table thead tr th').eq(1).should('have.text', 'First');
41+
cy.get('table thead tr th').eq(2).should('have.text', 'Second');
3742
cy.get('.pf-v5-c-table__toggle-icon').should('have.length', 10);
3843
});
3944

4045
it('can be passed a selectVariant to render radio buttons', () => {
41-
const SkeletonTableExample = <SkeletonTable rows={10} columns={[ 'first', 'second' ]} isSelectable selectVariant="radio" />;
46+
const SkeletonTableExample = <SkeletonTable rowsCount={10} columns={[ 'First', 'Second' ]} isSelectable selectVariant={RowSelectVariant.radio} />;
4247
cy.mount(SkeletonTableExample);
4348
cy.get('table').should('exist');
44-
cy.get('table thead tr').should('have.text', 'firstsecond');
49+
cy.get('table thead tr th').eq(0).should('have.text', 'Data selection table header cell');
50+
cy.get('table thead tr th').eq(1).should('have.text', 'First');
51+
cy.get('table thead tr th').eq(2).should('have.text', 'Second');
4552
cy.get('input[type="radio"]').should('have.length', 10);
4653
});
4754

48-
it('can be passed custom columns', () => {
55+
it('can be passed custom columns props', () => {
4956
const SkeletonTableExample = (
5057
<SkeletonTable
5158
rows={10}
52-
columns={[
53-
<Th key="1" sort={{ columnIndex: 0, sortBy: { index: 0, direction: 'asc' } }}>
54-
first
55-
</Th>,
56-
<Th key="2">second</Th>,
57-
<Th key="3">third</Th>
59+
columns={[
60+
{ cell: 'first', props: { sort: { columnIndex: 0, sortBy: { index: 0, direction: 'asc' } } } },
61+
{ cell: 'second' },
62+
{ cell: 'third' }
5863
]}
5964
/>
6065
);
6166
cy.mount(SkeletonTableExample);
6267
cy.get('table').should('exist');
63-
cy.get('table thead tr').should('have.text', 'firstsecondthird');
68+
cy.get('table thead tr th').eq(0).should('have.text', 'first');
69+
cy.get('table thead tr th').eq(1).should('have.text', 'second');
70+
cy.get('table thead tr th').eq(2).should('have.text', 'third');
6471
cy.get('.pf-v5-c-table__sort-indicator').eq(0).find('path').should(
6572
'have.attr',
6673
'd',
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React from 'react';
2+
import { RowSelectVariant } from '@patternfly/react-table';
3+
import SkeletonTableBody from '@patternfly/react-component-groups/dist/dynamic/SkeletonTableBody';
4+
5+
describe('SkeletonTableBody', () => {
6+
beforeEach(() => {
7+
cy.viewport(1600, 800);
8+
});
9+
10+
it('renders SkeletonTableBody', () => {
11+
const SkeletonTableExample = <SkeletonTableBody rowsCount={10} columnsCount={2} />;
12+
cy.mount(SkeletonTableExample);
13+
cy.get('div[class="pf-v5-c-skeleton"]').should('have.length', 20);
14+
});
15+
16+
it('contains checkboxes when passed isSelectable', () => {
17+
cy.mount(<SkeletonTableBody rowsCount={10} columnsCount={2} isSelectable />);
18+
cy.get('input[type="checkbox"]').should('have.length', 10);
19+
});
20+
21+
it('is expandable when passed isExpandable', () => {
22+
cy.mount(<SkeletonTableBody rowsCount={10} columnsCount={2} isExpandable />);
23+
cy.get('.pf-v5-c-table__toggle-icon').should('have.length', 10);
24+
});
25+
26+
it('can be passed a selectVariant to render radio buttons', () => {
27+
cy.mount(<SkeletonTableBody rowsCount={10} columnsCount={2} isSelectable selectVariant={RowSelectVariant.radio} />);
28+
cy.get('input[type="radio"]').should('have.length', 10);
29+
});
30+
});
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React from 'react';
2+
import { Table } from '@patternfly/react-table';
3+
import { SkeletonTableHead } from '@patternfly/react-component-groups/dist/dynamic/SkeletonTableHead';
4+
5+
describe('SkeletonTableHead', () => {
6+
beforeEach(() => {
7+
cy.viewport(1600, 800);
8+
});
9+
10+
it('renders SkeletonTable with custom columns', () => {
11+
const SkeletonTableExample = (
12+
<Table>
13+
<SkeletonTableHead columns={[ 'First', 'Second' ]} />
14+
</Table>
15+
);
16+
cy.mount(SkeletonTableExample);
17+
cy.get('table thead tr th').eq(0).should('have.text', 'First');
18+
cy.get('table thead tr th').eq(1).should('have.text', 'Second');
19+
});
20+
21+
it('renders SkeletonTable with column count but no custom columns', () => {
22+
const SkeletonTableExample = (
23+
<Table>
24+
<SkeletonTableHead columnsCount={2} />
25+
</Table>
26+
);
27+
cy.mount(SkeletonTableExample);
28+
cy.get('table thead tr th').should('have.length', 2);
29+
cy.get('table thead tr th').each((th) => {
30+
cy.wrap(th).find('.pf-v5-c-skeleton').should('exist');
31+
});
32+
});
33+
34+
it('renders SkeletonTable with selectable column', () => {
35+
const SkeletonTableExample = (
36+
<Table>
37+
<SkeletonTableHead columns={[ 'First' ]} isSelectable />
38+
</Table>
39+
);
40+
cy.mount(SkeletonTableExample);
41+
cy.get('table thead tr th').should('have.length', 2);
42+
cy.get('table thead tr th').eq(0).should('have.text', 'Data selection table header cell');
43+
});
44+
45+
it('renders SkeletonTable with expandable column', () => {
46+
const SkeletonTableExample = (
47+
<Table>
48+
<SkeletonTableHead columns={[ 'First' ]} isExpandable />
49+
</Table>
50+
);
51+
cy.mount(SkeletonTableExample);
52+
cy.get('table thead tr th').should('have.length', 2);
53+
cy.get('table thead tr th').eq(0).should('have.text', 'Data expansion table header cell');
54+
});
55+
56+
it('renders SkeletonTable with selectable and expandable columns', () => {
57+
const SkeletonTableExample = (
58+
<Table>
59+
<SkeletonTableHead columns={[ 'First', 'Second' ]} isSelectable isExpandable />
60+
</Table>
61+
);
62+
cy.mount(SkeletonTableExample);
63+
cy.get('table thead tr th').should('have.length', 4);
64+
});
65+
66+
it('renders SkeletonTable with custom ouiaId', () => {
67+
const customOuiaId = 'CustomOuia';
68+
const SkeletonTableExample = (
69+
<Table>
70+
<SkeletonTableHead columns={[ 'First', 'Second' ]} ouiaId={customOuiaId} />
71+
</Table>
72+
);
73+
cy.mount(SkeletonTableExample);
74+
cy.get('thead').should('have.attr', 'data-ouia-component-id', `${customOuiaId}-thead`);
75+
cy.get('th').each((th, index) => {
76+
cy.wrap(th).should('have.attr', 'data-ouia-component-id', `${customOuiaId}-th-${index}`);
77+
});
78+
});
79+
80+
it('handles no columns and no columnsCount', () => {
81+
const SkeletonTableExample = (
82+
<Table>
83+
<SkeletonTableHead />
84+
</Table>
85+
);
86+
cy.mount(SkeletonTableExample);
87+
cy.get('table thead tr th').should('have.length', 1);
88+
});
89+
});

packages/module/patternfly-docs/content/extensions/component-groups/examples/Skeleton/SkeletonTableCompactExample.tsx

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/module/patternfly-docs/content/extensions/component-groups/examples/Skeleton/SkeletonTableExample.tsx

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/module/patternfly-docs/content/extensions/component-groups/examples/Skeleton/SkeletonTableExpandableExample.tsx

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/module/patternfly-docs/content/extensions/component-groups/examples/Skeleton/SkeletonTableLoadingExample.tsx

Lines changed: 0 additions & 101 deletions
This file was deleted.

packages/module/patternfly-docs/content/extensions/component-groups/examples/Skeleton/SkeletonTableSelectableExample.tsx

Lines changed: 0 additions & 6 deletions
This file was deleted.

packages/module/patternfly-docs/content/extensions/component-groups/examples/Skeleton/Skeleton.md renamed to packages/module/patternfly-docs/content/extensions/component-groups/examples/SkeletonTable/SkeletonTable.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ id: Skeleton table
1010
source: react
1111
# If you use typescript, the name of the interface to display props for
1212
# These are found through the sourceProps function provided in patternfly-docs.source.js
13-
propComponents: ['SkeletonTable']
14-
sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/Skeleton/Skeleton.md
13+
propComponents: ['SkeletonTable', 'SkeletonTableHead', 'SkeletonTableBody']
14+
sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/SkeletonTable/SkeletonTable.md
1515
---
16+
import { RowSelectVariant, TableVariant, Table } from '@patternfly/react-table';
1617
import SkeletonTable from '@patternfly/react-component-groups/dist/dynamic/SkeletonTable';
18+
import SkeletonTableHead from '@patternfly/react-component-groups/dist/dynamic/SkeletonTableHead';
19+
import SkeletonTableBody from '@patternfly/react-component-groups/dist/dynamic/SkeletonTableBody';
1720

1821
The **skeleton table** component is used to display placeholder "skeletons" within a table as its contents load.
1922

@@ -63,9 +66,25 @@ Custom column headers can be provided by passing an array of strings or `Th` com
6366

6467
The following example demonstrates the typical behavior of a skeleton table transitioning to a normal table as the data becomes available.
6568

66-
To simulate this loading process, select the `Reload table` button and wait for the data to populate.
69+
To simulate this loading process, click the "Reload table" button and wait for the data to populate.
6770

6871

6972
```js file="./SkeletonTableLoadingExample.tsx"
7073

7174
```
75+
76+
### Skeleton table head
77+
78+
You can render only the `<Thead>` part of the skeleton table by using the `<SkeletonTableHead/>`.
79+
80+
```js file="./SkeletonTableHeadExample.tsx"
81+
82+
```
83+
84+
### Skeleton table body
85+
86+
You can also render only the `<Tbody>` part of the skeleton table by using the `<SkeletonTableBody/>`.
87+
88+
```js file="./SkeletonTableBodyExample.tsx"
89+
90+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React from 'react';
2+
import { Table } from '@patternfly/react-table';
3+
import SkeletonTableBody from "@patternfly/react-component-groups/dist/dynamic/SkeletonTableBody";
4+
5+
export const SkeletonTableBodyExample: React.FC = () => (
6+
<Table>
7+
<SkeletonTableBody isSelectable rowsCount={5} columnsCount={2} />
8+
</Table>
9+
);

0 commit comments

Comments
 (0)