Skip to content

Commit

Permalink
feat(table): add Table and Pagination Components (#40)
Browse files Browse the repository at this point in the history
* feat(table): add Table and Pagination Components

* feat(table): changed totalCount to totalRows
  • Loading branch information
mgray-sonalake authored Feb 21, 2022
1 parent 2eefed4 commit 0cbee08
Show file tree
Hide file tree
Showing 41 changed files with 1,554 additions and 47 deletions.
10 changes: 7 additions & 3 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@
"plugins": ["import", "simple-import-sort", "jest", "testing-library"],
"extends": [
"react-app",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript"
"plugin:import/recommended",
"plugin:import/typescript",
"plugin:storybook/recommended"
],
"ignorePatterns": ["dist/"],
"rules": {
"no-console": "warn",
"no-nested-ternary": "error",
"react/self-closing-comp": "warn",
"react/button-has-type": "warn",
"jest/no-focused-tests": "error",
"import/first": "error",
"import/no-duplicates": "error",
"import/namespace": "off",
"import/no-named-as-default": 0,
"simple-import-sort/imports": [
"error",
{
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

jobs:
quality:
name: Build and Deploy
name: Quality and Build
runs-on: ubuntu-latest

steps:
Expand Down Expand Up @@ -42,7 +42,7 @@ jobs:
run: yarn build:storybook

publish:
name: Publish
name: Publish and Deploy
if: ${{ github.ref == 'refs/heads/master' }}
needs: [quality]
runs-on: ubuntu-latest
Expand Down
20 changes: 19 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@
"@radix-ui/react-alert-dialog": "^0.1.5",
"@radix-ui/react-tooltip": "^0.1.6",
"clsx": "^1.1.1",
"react": ">=16"
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"react": ">=16",
"react-icons": "^4.3.1",
"react-table": "^7.7.0"
},
"husky": {
"hooks": {
Expand Down Expand Up @@ -82,30 +86,44 @@
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"@types/jest-axe": "^3.5.3",
"@types/lodash": "^4.14.178",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11",
"@types/react-table": "^7.7.9",
"@types/regenerator-runtime": "^0.13.1",
"@types/tailwindcss": "^3.0.7",
"@typescript-eslint/eslint-plugin": "^5.12.0",
"@typescript-eslint/parser": "^5.12.0",
"autoprefixer": "^10.4.2",
"babel-loader": "^8.2.3",
"copyfiles": "^2.4.1",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^8.9.0",
"eslint-config-react-app": "^7.0.0",
"eslint-plugin-flowtype": "^8.0.3",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.0",
"eslint-plugin-jest-dom": "^4.0.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-simple-import-sort": "^7.0.0",
"eslint-plugin-storybook": "^0.5.7",
"eslint-plugin-testing-library": "^5.0.5",
"husky": "^7.0.4",
"identity-obj-proxy": "^3.0.0",
"jest-axe": "^5.0.1",
"jest-junit": "^13.0.0",
"jest-transform-stub": "^2.0.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"postcss": "^8.4.6",
"postcss-loader": "^6.2.1",
"prettier": "^2.5.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-icons": "^4.3.1",
"react-is": "^17.0.2",
"react-table": "^7.7.0",
"regenerator-runtime": "^0.13.9",
"rollup-plugin-postcss": "^4.0.2",
"semantic-release": "^19.0.2",
Expand Down
41 changes: 41 additions & 0 deletions src/declarations/react-table-config.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export interface CustomColumnOptions {
headerCellClassName?: string;
}

declare module 'react-table' {
// source: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-table

export interface TableOptions<D extends object>
extends UseFiltersOptions<D>,
UseGlobalFiltersOptions<D>,
UsePaginationOptions<D>,
UseSortByOptions<D>,
// note that having Record here allows you to add anything to the options, this matches the spirit of the
// underlying js library, but might be cleaner if it's replaced by a more specific type that matches your
// feature set, this is a safe default.
Record<string, any> {}

export interface Hooks<D extends object = {}> extends UseSortByHooks<D> {}

export interface TableInstance<D extends object = {}>
extends UseFiltersInstanceProps<D>,
UseGlobalFiltersInstanceProps<D>,
UsePaginationInstanceProps<D>,
UseSortByInstanceProps<D> {}

export interface TableState<D extends object = {}>
extends UseFiltersState<D>,
UseGlobalFiltersState<D>,
UsePaginationState<D>,
UseSortByState<D> {}

export interface ColumnInterface<D extends object = {}>
extends UseFiltersColumnOptions<D>,
UseGlobalFiltersColumnOptions<D>,
UseSortByColumnOptions<D>,
CustomColumnOptions {}

export interface ColumnInstance<D extends object = {}>
extends UseFiltersColumnProps<D>,
UseSortByColumnProps<D> {}
}
1 change: 1 addition & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './use-context-fallback.hook';
15 changes: 15 additions & 0 deletions src/hooks/use-context-fallback.hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Context, useContext } from 'react';

export const useContextFallback = <T>(value: Context<T | undefined>): T => {
const context = useContext<T | undefined>(value);

if (context === undefined) {
throw new Error(
`Components that require this context must be children of ${
value.displayName ?? 'the appropriate provider'
}.`
);
}

return context;
};
1 change: 1 addition & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import './style.css';

export * from './hooks';
export * from './models';
export * from './ui';
6 changes: 3 additions & 3 deletions src/ui/alert/alert.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@ describe('Alert', () => {
const { container } = render(
<Alert>
<AlertTrigger asChild>
<button>Trigger</button>
<button type="button">Trigger</button>
</AlertTrigger>
<AlertContent>
<AlertTitle>Title</AlertTitle>
<AlertDescription>Description</AlertDescription>
<AlertCancel asChild>
<button>Cancel</button>
<button type="button">Cancel</button>
</AlertCancel>
<AlertAction asChild>
<button>Action</button>
<button type="button">Action</button>
</AlertAction>
</AlertContent>
</Alert>
Expand Down
10 changes: 5 additions & 5 deletions src/ui/alert/alert.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ export default meta;
export const Error: ComponentStory<typeof Alert> = () => (
<Alert>
<AlertTrigger asChild>
<button>Show error</button>
<button type="button">Show error</button>
</AlertTrigger>
<AlertContent size="sm">
<AlertTitle icon={<MdError />}>Error</AlertTitle>
<AlertDescription>This is the content of the Error.</AlertDescription>
<AlertCancel asChild>
<button>Close</button>
<button type="button">Close</button>
</AlertCancel>
</AlertContent>
</Alert>
Expand All @@ -37,7 +37,7 @@ export const Error: ComponentStory<typeof Alert> = () => (
export const Confirmation: ComponentStory<typeof Alert> = () => (
<Alert>
<AlertTrigger asChild>
<button>Delete account</button>
<button type="button">Delete account</button>
</AlertTrigger>
<AlertContent>
<AlertTitle icon={<MdWarning />}>
Expand All @@ -46,10 +46,10 @@ export const Confirmation: ComponentStory<typeof Alert> = () => (
<AlertDescription>This action cannot be undone.</AlertDescription>
<div className="flex space-x-6">
<AlertCancel asChild>
<button>Cancel</button>
<button type="button">Cancel</button>
</AlertCancel>
<AlertAction asChild>
<button>Continue</button>
<button type="button">Continue</button>
</AlertAction>
</div>
</AlertContent>
Expand Down
2 changes: 2 additions & 0 deletions src/ui/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export * from './alert';
export * from './label';
export * from './pagination';
export * from './property-item';
export * from './table';
export * from './typography';
2 changes: 2 additions & 0 deletions src/ui/pagination/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './pagination-info.component';
export * from './pagination-navigation.component';
30 changes: 30 additions & 0 deletions src/ui/pagination/components/page-size-select.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';

import { usePaginationContext } from '../context';

export const PageSizeSelect = () => {
const {
pageSize,
pageSizeOptions = [],
onPageSizeChange,
} = usePaginationContext();

return (
<div className="mr-4">
<label htmlFor="pagination" className="text-neutral-400 hidden">
Rows per page:
</label>
<select
id="pagination"
value={pageSize}
onChange={(event) => onPageSizeChange?.(Number(event.target.value))}
>
{pageSizeOptions.map((size) => (
<option key={size} value={size}>
{size}
</option>
))}
</select>
</div>
);
};
24 changes: 24 additions & 0 deletions src/ui/pagination/components/pages.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';

import { PaginationButton } from './pagination-button.component';

type PagesProps = {
pages: number[];
pageIndex: number;
onPageClick: (page: number) => void;
};

export const Pages = ({ pages, pageIndex, onPageClick }: PagesProps) => (
<>
{pages.map((page) => (
<PaginationButton
isActive={pageIndex + 1 === page}
key={page}
label={`Page ${page}`}
onClick={() => onPageClick(page - 1)}
>
{page}
</PaginationButton>
))}
</>
);
29 changes: 29 additions & 0 deletions src/ui/pagination/components/pagination-button.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import clsx from 'clsx';

type PaginationButtonProps = {
label: string;
children: React.ReactNode;
isActive?: boolean;
disabled?: boolean;
onClick: () => void;
};

export const PaginationButton = ({
label,
children,
isActive,
disabled,
onClick,
}: PaginationButtonProps) => (
<button
type="button"
disabled={disabled}
aria-label={label}
title={label}
onClick={onClick}
className={clsx('p-2', { 'bg-neutral-400': isActive })}
>
{children}
</button>
);
3 changes: 3 additions & 0 deletions src/ui/pagination/components/pagination-dots.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import React from 'react';

export const PaginationDots = () => <div>...</div>;
18 changes: 18 additions & 0 deletions src/ui/pagination/components/pagination-info.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import { isEmpty as _isEmpty } from 'lodash';

import { usePaginationContext } from '../context';
import { PageSizeSelect } from './page-size-select.component';
import { PaginationResults } from './pagination-results.component';

export const PaginationInfo = () => {
const { pageSizeOptions, totalRows } = usePaginationContext();

return (
<div className="flex">
{totalRows !== undefined && <PaginationResults />}

{!_isEmpty(pageSizeOptions) && <PageSizeSelect />}
</div>
);
};
29 changes: 29 additions & 0 deletions src/ui/pagination/components/pagination-navigation.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { MdChevronLeft, MdChevronRight } from 'react-icons/md';

import { usePaginationContext } from '../context';
import { PaginationButton } from './pagination-button.component';
import { PaginationRange } from './pagination-range.component';

export const PaginationNavigation = () => {
const { previousPage, nextPage, canPreviousPage, canNextPage } =
usePaginationContext();

return (
<nav className="flex items-center space-x-2" aria-label="Pagination">
<PaginationButton
label="Next"
disabled={!canPreviousPage}
onClick={previousPage}
>
<MdChevronLeft />
</PaginationButton>

<PaginationRange />

<PaginationButton label="Prev" disabled={!canNextPage} onClick={nextPage}>
<MdChevronRight />
</PaginationButton>
</nav>
);
};
Loading

0 comments on commit 0cbee08

Please sign in to comment.