Skip to content
Merged
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
45 changes: 26 additions & 19 deletions cypress/component/SkeletonTable.cy.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,73 @@
import React from 'react';
import { Th } from '@patternfly/react-table';
import SkeletonTable from '../../packages/module/dist/dynamic/SkeletonTable';
import { RowSelectVariant } from '@patternfly/react-table';
import SkeletonTable from '@patternfly/react-component-groups/dist/dynamic/SkeletonTable';

describe('SkeletonTable', () => {
beforeEach(() => {
cy.viewport(1600, 800);
});

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

it ('can be used without passing columns', () => {
const SkeletonTableExample = <SkeletonTable rows={10} numberOfColumns={2} />;
const SkeletonTableExample = <SkeletonTable rowsCount={10} columnsCount={2} />;
cy.mount(SkeletonTableExample);
cy.get('table').should('exist');
cy.get('table thead tr').should('have.text', '');
});

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

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

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

it('can be passed custom columns', () => {
it('can be passed custom columns props', () => {
const SkeletonTableExample = (
<SkeletonTable
rows={10}
columns={[
<Th key="1" sort={{ columnIndex: 0, sortBy: { index: 0, direction: 'asc' } }}>
first
</Th>,
<Th key="2">second</Th>,
<Th key="3">third</Th>
columns={[
{ cell: 'first', props: { sort: { columnIndex: 0, sortBy: { index: 0, direction: 'asc' } } } },
{ cell: 'second' },
{ cell: 'third' }
]}
/>
);
cy.mount(SkeletonTableExample);
cy.get('table').should('exist');
cy.get('table thead tr').should('have.text', 'firstsecondthird');
cy.get('table thead tr th').eq(0).should('have.text', 'first');
cy.get('table thead tr th').eq(1).should('have.text', 'second');
cy.get('table thead tr th').eq(2).should('have.text', 'third');
cy.get('.pf-v5-c-table__sort-indicator').eq(0).find('path').should(
'have.attr',
'd',
Expand Down
30 changes: 30 additions & 0 deletions cypress/component/SkeletonTableBody.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { RowSelectVariant } from '@patternfly/react-table';
import SkeletonTableBody from '@patternfly/react-component-groups/dist/dynamic/SkeletonTableBody';

describe('SkeletonTableBody', () => {
beforeEach(() => {
cy.viewport(1600, 800);
});

it('renders SkeletonTableBody', () => {
const SkeletonTableExample = <SkeletonTableBody rowsCount={10} columnsCount={2} />;
cy.mount(SkeletonTableExample);
cy.get('div[class="pf-v5-c-skeleton"]').should('have.length', 20);
});

it('contains checkboxes when passed isSelectable', () => {
cy.mount(<SkeletonTableBody rowsCount={10} columnsCount={2} isSelectable />);
cy.get('input[type="checkbox"]').should('have.length', 10);
});

it('is expandable when passed isExpandable', () => {
cy.mount(<SkeletonTableBody rowsCount={10} columnsCount={2} isExpandable />);
cy.get('.pf-v5-c-table__toggle-icon').should('have.length', 10);
});

it('can be passed a selectVariant to render radio buttons', () => {
cy.mount(<SkeletonTableBody rowsCount={10} columnsCount={2} isSelectable selectVariant={RowSelectVariant.radio} />);
cy.get('input[type="radio"]').should('have.length', 10);
});
});
89 changes: 89 additions & 0 deletions cypress/component/SkeletonTableHead.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from 'react';
import { Table } from '@patternfly/react-table';
import { SkeletonTableHead } from '@patternfly/react-component-groups/dist/dynamic/SkeletonTableHead';

describe('SkeletonTableHead', () => {
beforeEach(() => {
cy.viewport(1600, 800);
});

it('renders SkeletonTable with custom columns', () => {
const SkeletonTableExample = (
<Table>
<SkeletonTableHead columns={[ 'First', 'Second' ]} />
</Table>
);
cy.mount(SkeletonTableExample);
cy.get('table thead tr th').eq(0).should('have.text', 'First');
cy.get('table thead tr th').eq(1).should('have.text', 'Second');
});

it('renders SkeletonTable with column count but no custom columns', () => {
const SkeletonTableExample = (
<Table>
<SkeletonTableHead columnsCount={2} />
</Table>
);
cy.mount(SkeletonTableExample);
cy.get('table thead tr th').should('have.length', 2);
cy.get('table thead tr th').each((th) => {
cy.wrap(th).find('.pf-v5-c-skeleton').should('exist');
});
});

it('renders SkeletonTable with selectable column', () => {
const SkeletonTableExample = (
<Table>
<SkeletonTableHead columns={[ 'First' ]} isSelectable />
</Table>
);
cy.mount(SkeletonTableExample);
cy.get('table thead tr th').should('have.length', 2);
cy.get('table thead tr th').eq(0).should('have.text', 'Data selection table header cell');
});

it('renders SkeletonTable with expandable column', () => {
const SkeletonTableExample = (
<Table>
<SkeletonTableHead columns={[ 'First' ]} isExpandable />
</Table>
);
cy.mount(SkeletonTableExample);
cy.get('table thead tr th').should('have.length', 2);
cy.get('table thead tr th').eq(0).should('have.text', 'Data expansion table header cell');
});

it('renders SkeletonTable with selectable and expandable columns', () => {
const SkeletonTableExample = (
<Table>
<SkeletonTableHead columns={[ 'First', 'Second' ]} isSelectable isExpandable />
</Table>
);
cy.mount(SkeletonTableExample);
cy.get('table thead tr th').should('have.length', 4);
});

it('renders SkeletonTable with custom ouiaId', () => {
const customOuiaId = 'CustomOuia';
const SkeletonTableExample = (
<Table>
<SkeletonTableHead columns={[ 'First', 'Second' ]} ouiaId={customOuiaId} />
</Table>
);
cy.mount(SkeletonTableExample);
cy.get('thead').should('have.attr', 'data-ouia-component-id', `${customOuiaId}-thead`);
cy.get('th').each((th, index) => {
cy.wrap(th).should('have.attr', 'data-ouia-component-id', `${customOuiaId}-th-${index}`);
});
});

it('handles no columns and no columnsCount', () => {
const SkeletonTableExample = (
<Table>
<SkeletonTableHead />
</Table>
);
cy.mount(SkeletonTableExample);
cy.get('table thead tr th').should('have.length', 1);
});
});

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ id: Skeleton table
source: react
# If you use typescript, the name of the interface to display props for
# These are found through the sourceProps function provided in patternfly-docs.source.js
propComponents: ['SkeletonTable']
sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/Skeleton/Skeleton.md
propComponents: ['SkeletonTable', 'SkeletonTableHead', 'SkeletonTableBody']
sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/SkeletonTable/SkeletonTable.md
---
import { RowSelectVariant, TableVariant, Table } from '@patternfly/react-table';
import SkeletonTable from '@patternfly/react-component-groups/dist/dynamic/SkeletonTable';
import SkeletonTableHead from '@patternfly/react-component-groups/dist/dynamic/SkeletonTableHead';
import SkeletonTableBody from '@patternfly/react-component-groups/dist/dynamic/SkeletonTableBody';

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

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

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

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


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

```

### Skeleton table head

You can render only the `<Thead>` part of the skeleton table by using the `<SkeletonTableHead/>`.

```js file="./SkeletonTableHeadExample.tsx"

```

### Skeleton table body

You can also render only the `<Tbody>` part of the skeleton table by using the `<SkeletonTableBody/>`.

```js file="./SkeletonTableBodyExample.tsx"

```
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import { Table } from '@patternfly/react-table';
import SkeletonTableBody from "@patternfly/react-component-groups/dist/dynamic/SkeletonTableBody";

export const SkeletonTableBodyExample: React.FC = () => (
<Table>
<SkeletonTableBody isSelectable rowsCount={5} columnsCount={2} />
</Table>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react';
import SkeletonTable from "@patternfly/react-component-groups/dist/dynamic/SkeletonTable";
import { TableVariant } from '@patternfly/react-table';

export const SkeletonTableExample: React.FC = () => <SkeletonTable rowsCount={10} columns={[ 'First', 'Second' ]} variant={TableVariant.compact} borders={false} />;
Loading