diff --git a/frontend/.storybook/preview.js b/frontend/.storybook/preview.js index 1fef7cf80..2a3a61d5a 100644 --- a/frontend/.storybook/preview.js +++ b/frontend/.storybook/preview.js @@ -1,8 +1,22 @@ -import { themes } from '@storybook/theming'; -import '../src/styles/globals.css'; +import { themes } from "@storybook/theming"; +import "react-day-picker/dist/style.css"; +import "../src/styles/globals.css"; export const parameters = { - actions: { argTypesRegex: '^on[A-Z].*' }, + actions: { argTypesRegex: "^on[A-Z].*" }, + backgrounds: { + default: "dark", + values: [ + { + name: "dark", + value: "rgb(14, 16, 20)" + }, + { + name: "paper", + value: "rgb(30, 31, 34)" + } + ] + }, controls: { matchers: { color: /(background|color)$/i, @@ -10,6 +24,6 @@ export const parameters = { } }, darkMode: { - dark: { ...themes.dark, appContentBg: 'rgb(14,16,20)', appBg: 'rgb(14,16,20)' } + dark: { ...themes.dark, appContentBg: "rgb(14,16,20)", appBg: "rgb(14,16,20)" } } }; diff --git a/frontend/src/components/v2/Pagination/Pagination.stories.tsx b/frontend/src/components/v2/Pagination/Pagination.stories.tsx new file mode 100644 index 000000000..fd10ef8c6 --- /dev/null +++ b/frontend/src/components/v2/Pagination/Pagination.stories.tsx @@ -0,0 +1,29 @@ +// eslint-disable-next-line +import { useArgs } from "@storybook/client-api"; +import type { Meta } from "@storybook/react"; + +import { Pagination, PaginationProps } from "./Pagination"; + +const meta: Meta = { + title: "Components/Pagination", + component: Pagination, + tags: ["v2"], + args: { + count: 50 + } +}; + +export default meta; +// type Story = StoryObj; + +export const Primary = (args: PaginationProps) => { + const [, updateArgs] = useArgs(); + + return ( + updateArgs({ page })} + onChangePerPage={(perPage) => updateArgs({ perPage, page: 1 })} + /> + ); +}; diff --git a/frontend/src/components/v2/Pagination/Pagination.tsx b/frontend/src/components/v2/Pagination/Pagination.tsx new file mode 100644 index 000000000..99d50a07f --- /dev/null +++ b/frontend/src/components/v2/Pagination/Pagination.tsx @@ -0,0 +1,95 @@ +import { + faCaretDown, + faCheck, + faChevronLeft, + faChevronRight +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { twMerge } from "tailwind-merge"; + +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger +} from "../Dropdown"; +import { IconButton } from "../IconButton"; + +export type PaginationProps = { + count: number; + page: number; + perPage?: number; + onChangePage: (pageNumber: number) => void; + onChangePerPage: (newRows: number) => void; + className: string; + perPageList?: number[]; +}; + +export const Pagination = ({ + count, + page = 1, + perPage = 20, + onChangePage, + onChangePerPage, + perPageList = [10, 20, 50, 100], + className +}: PaginationProps) => { + const prevPageNumber = Math.max(1, page - 1); + const canGoPrev = page > 1; + + const upperLimit = Math.ceil(count / perPage); + const nextPageNumber = Math.min(upperLimit, page + 1); + const canGoNext = page + 1 <= upperLimit; + + return ( +
+
+
+ {(page - 1) * perPage} - {(page - 1) * perPage + perPage} of {count} +
+ + + + + + + + {perPageList.map((perPageOption) => ( + } + iconPos="right" + onClick={() => onChangePerPage(perPageOption)} + > + {perPageOption} rows per page + + ))} + + +
+
+ onChangePage(prevPageNumber)} + isDisabled={!canGoPrev} + > + + + onChangePage(nextPageNumber)} + isDisabled={!canGoNext} + > + + +
+
+ ); +}; diff --git a/frontend/src/components/v2/Pagination/index.tsx b/frontend/src/components/v2/Pagination/index.tsx new file mode 100644 index 000000000..583a0b550 --- /dev/null +++ b/frontend/src/components/v2/Pagination/index.tsx @@ -0,0 +1,2 @@ +export type { PaginationProps } from "./Pagination"; +export { Pagination } from "./Pagination";