Skip to content

Commit

Permalink
Table: Create table components (#695)
Browse files Browse the repository at this point in the history
* feat(table): add pharos table component

* feat(table): add more to tables

* feat(table): implement page size dropdown

* feat(table): add react storybook

* feat(table): add unit tests to table

* docs(table): add changeset

* feat(table): update storybook

* feat(table): improve storybook reactivity

* feat(table): add accessibility update

* feat(table): use pharos color

* feat(table): fix bug

* feat(table): fix build issue

* Update packages/pharos/src/components/table/pharos-table.ts

Co-authored-by: Dane Hillard <github@danehillard.com>

* Update packages/pharos/src/components/table/pharos-table.ts

Co-authored-by: Dane Hillard <github@danehillard.com>

* feat(table): fix pagination height and remove any type

* feat(table): add unit test for start and end page number

* Update packages/pharos/src/components/table/pharos-table.test.ts

Co-authored-by: Dane Hillard <github@danehillard.com>

* Update packages/pharos/src/components/table/pharos-table.test.ts

Co-authored-by: Dane Hillard <github@danehillard.com>

* Update packages/pharos/src/components/table/pharos-table.test.ts

Co-authored-by: Dane Hillard <github@danehillard.com>

* feat(table): update row data type

* feat(table): update unit test

* feat(table): add hide caption visually attribute

* feat(table): update visually hidden css

* feat(table): use hidden mixin

* feat(table): fix lint and bug

* feat(table): fix unit tests

* Update packages/pharos/src/components/table/pharos-table.ts

Co-authored-by: Dane Hillard <github@danehillard.com>

* Update packages/pharos/src/components/table/pharos-table.test.ts

Co-authored-by: Brent Swisher <brent@brentswisher.com>

* Update packages/pharos/src/components/table/pharos-table.ts

Co-authored-by: Mat Harris <mat.harris@ithaka.org>

* Update packages/pharos/src/components/table/pharos-table.ts

Co-authored-by: Mat Harris <mat.harris@ithaka.org>

* Update packages/pharos/src/components/table/pharos-table.ts

Co-authored-by: Mat Harris <mat.harris@ithaka.org>

* feat(table): update attribute name and add unit test

---------

Co-authored-by: Dane Hillard <github@danehillard.com>
Co-authored-by: Brent Swisher <brent@brentswisher.com>
Co-authored-by: Mat Harris <mat.harris@ithaka.org>
  • Loading branch information
4 people authored Mar 14, 2024
1 parent 976ac61 commit b864531
Show file tree
Hide file tree
Showing 11 changed files with 607 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/orange-fireants-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ithaka/pharos': minor
---

Create table component
2 changes: 2 additions & 0 deletions .storybook/initComponents.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
PharosSidenavSection,
PharosTabs,
PharosTab,
PharosTable,
PharosTabPanel,
PharosTextInput,
PharosTextarea,
Expand Down Expand Up @@ -86,6 +87,7 @@ registerComponents('storybook', [
PharosSidenavSection,
PharosTabs,
PharosTab,
PharosTable,
PharosTabPanel,
PharosTextInput,
PharosTextarea,
Expand Down
1 change: 1 addition & 0 deletions packages/pharos-site/initComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ if (typeof window !== `undefined`) {
pharos.PharosSidenavSection,
pharos.PharosTabs,
pharos.PharosTab,
pharos.PharosTable,
pharos.PharosTabPanel,
pharos.PharosTextInput,
pharos.PharosTextarea,
Expand Down
52 changes: 52 additions & 0 deletions packages/pharos/src/components/table/PharosTable.react.stories.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { PharosTable } from '../../react-components';
import { configureDocsPage } from '@config/docsPageConfig';
import { PharosContext } from '../../utils/PharosContext';
import { defaultArgs } from './storyArgs';

export default {
title: 'Components/Table',
component: PharosTable,
decorators: [
(Story) => (
<PharosContext.Provider value={{ prefix: 'storybook' }}>
<Story />
</PharosContext.Provider>
),
],
parameters: {
docs: { page: configureDocsPage('table') },
options: { selectedPanel: 'addon-controls' },
},
};

export const Base = {
render: (args) => (
<PharosTable
columns={args.columns}
rowData={args.rowData}
showPagination={args.showPagination}
caption={'An example table'}
></PharosTable>
),
args: {
...defaultArgs,
showPagination: false,
},
};

export const WithPagination = {
render: (args) => (
<PharosTable
columns={args.columns}
rowData={args.rowData}
showPagination={args.showPagination}
totalResults={5}
pageSizeOptions={[2, 4]}
caption={'An example table'}
></PharosTable>
),
args: {
...defaultArgs,
showPagination: true,
},
};
45 changes: 45 additions & 0 deletions packages/pharos/src/components/table/pharos-table.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
@use '../../utils/scss/mixins';

:host {
display: inline-flex;
flex-direction: column;
}

.table {
border-collapse: collapse;

th {
border: 1px solid var(--pharos-color-marble-gray-base);
padding: var(--pharos-spacing-1-x);
}

td {
border: 1px solid var(--pharos-color-marble-gray-base);
padding: var(--pharos-spacing-1-x);
}
}

.table-controls {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: var(--pharos-spacing-one-half-x);

.item-per-page-wrapper {
display: flex;
align-items: center;
column-gap: var(--pharos-spacing-one-half-x);

.item-per-page-selector {
width: 75px;
}
}

.pagination {
height: var(--pharos-spacing-one-and-a-half-x);
}
}

.visually-hidden:not(:focus, :active) {
@include mixins.hidden;
}
174 changes: 174 additions & 0 deletions packages/pharos/src/components/table/pharos-table.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { fixture, expect } from '@open-wc/testing';
import type { TemplateResult } from 'lit';

import { html } from 'lit/static-html.js';

import type { PharosTable } from './pharos-table';
import type { PharosLink } from '../link/pharos-link';
import type { PharosPagination } from '../pagination/pharos-pagination';
import type { PharosSelect } from '../select/pharos-select';

describe('pharos-table', () => {
let component: PharosTable, componentWithPagination: PharosTable;
const columns = [
{
name: 'Item',
field: 'item',
},
{
name: 'Filename',
field: 'filename',
},
];
const rowData = [
{
item: 1,
filename: '12345.jpg',
expired_date: '2020-1-1',
created_on: '2010-1-1',
university: 'University of Michigan',
},
{
item: 2,
filename: '123456.jpg',
expired_date: '2020-1-1',
created_on: '2010-1-1',
university: 'University of Michigan',
},
];

beforeEach(async () => {
component = await fixture(html`
<test-pharos-table
.columns="${columns}"
.rowData="${rowData}"
.totalResults="${2}"
caption="test table"
>
</test-pharos-table>
`);

componentWithPagination = await fixture(html`
<test-pharos-table
.columns="${columns}"
.rowData="${rowData}"
.showPagination="${true}"
.totalResults="${2}"
.pageSizeOptions="${[1, 2]}"
caption="test table with pagination"
>
</test-pharos-table>
`);
});

it('is accessible', async () => {
await expect(component).to.be.accessible();
});

it('is accessible with pagination', async () => {
await expect(componentWithPagination).to.be.accessible();
});

it('has the correct number of rows', async () => {
const rows = Array.prototype.slice.call(
component.renderRoot.querySelectorAll(`tr`)
) as TemplateResult[];
expect(rows.length).to.be.eq(3);
});

it('renders rows according to page size', async () => {
const rows = Array.prototype.slice.call(
componentWithPagination.renderRoot.querySelectorAll(`tr`)
) as TemplateResult[];
expect(rows.length).to.be.eq(2);
});

it('shows correct page start number according to page size', async () => {
let pageNumber: HTMLElement | null =
componentWithPagination.renderRoot.querySelector(`.page-number-display`);
expect(pageNumber?.innerText).contains('Displaying 1-1 of 2');

const selectDropdown = componentWithPagination.renderRoot.querySelector(
`pharos-select`
) as PharosSelect;
selectDropdown['_select'].value = '2';
selectDropdown['_select'].dispatchEvent(new Event('change'));

await componentWithPagination.updateComplete;

pageNumber = componentWithPagination.renderRoot.querySelector(`.page-number-display`);
expect(pageNumber?.innerText).contains('Displaying 1-2 of 2');
});

it('updates correctly after page size selection', async () => {
let rows = Array.prototype.slice.call(
componentWithPagination.renderRoot.querySelectorAll(`tr`)
) as TemplateResult[];
expect(rows.length).to.be.eq(2);

const selectDropdown = componentWithPagination.renderRoot.querySelector(
`pharos-select`
) as PharosSelect;
selectDropdown['_select'].value = '2';
selectDropdown['_select'].dispatchEvent(new Event('change'));

await componentWithPagination.updateComplete;

rows = Array.prototype.slice.call(
componentWithPagination.renderRoot.querySelectorAll(`tr`)
) as TemplateResult[];
expect(rows.length).to.be.eq(3);
});

it('fires a custom event when going to previous and next page', async () => {
let prevWasFired = false;
let nextWasFired = false;
const handlePrevPage = (): void => {
prevWasFired = true;
};
const handleNextPage = (): void => {
nextWasFired = true;
};
componentWithPagination.addEventListener('pharos-table-prev-page', handlePrevPage);
componentWithPagination.addEventListener('pharos-table-next-page', handleNextPage);

const pagination = componentWithPagination.renderRoot.querySelector(
`pharos-pagination`
) as PharosPagination;
const nextPageLink = pagination.renderRoot.querySelector(`.next`) as PharosLink;
nextPageLink.click();
await componentWithPagination.updateComplete;

expect(nextWasFired).to.be.true;

const prevPageLink = pagination.renderRoot.querySelector(`.prev`) as PharosLink;
prevPageLink.click();
await componentWithPagination.updateComplete;

expect(prevWasFired).to.be.true;
});
});

it('throws an error if caption is not provided', async () => {
let errorThrown = false;
try {
await fixture(
html`<test-pharos-table
.columns="${[]}"
.rowData="${[]}"
.showPagination="${true}"
.totalResults="${2}"
.pageSizeOptions="${[1, 2]}"
>
</test-pharos-table> `
);
} catch (error) {
if (error instanceof Error) {
errorThrown = true;
expect(error?.message).to.be.equal(
'Table must have an accessible name. Please provide a caption for the table using the `caption` attribute. You can hide the caption visually by setting the `hide-caption-visually` property.'
);
}
}
expect(errorThrown).to.be.true;
});
Loading

0 comments on commit b864531

Please sign in to comment.