-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Table: Create table components (#695)
* 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
1 parent
976ac61
commit b864531
Showing
11 changed files
with
607 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@ithaka/pharos': minor | ||
--- | ||
|
||
Create table component |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
packages/pharos/src/components/table/PharosTable.react.stories.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
174
packages/pharos/src/components/table/pharos-table.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}); |
Oops, something went wrong.