Improve pagination + styles
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -10,15 +10,14 @@ import type { CSSProperties } from 'react';
|
||||
import { FC } from 'react';
|
||||
import { FocusEvent as FocusEvent_2 } from 'react';
|
||||
import { ForwardRefExoticComponent } from 'react';
|
||||
import { HTMLAttributes } from 'react';
|
||||
import { JSX as JSX_2 } from 'react/jsx-runtime';
|
||||
import { Menu as Menu_2 } from '@base-ui-components/react/menu';
|
||||
import { default as React_2 } from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
import { RefAttributes } from 'react';
|
||||
import type { RemixiconComponentType } from '@remixicon/react';
|
||||
import { ScrollArea as ScrollArea_2 } from '@base-ui-components/react/scroll-area';
|
||||
import { TdHTMLAttributes } from 'react';
|
||||
import { ThHTMLAttributes } from 'react';
|
||||
import { Table as Table_2 } from '@tanstack/react-table';
|
||||
import { Tooltip as Tooltip_2 } from '@base-ui-components/react/tooltip';
|
||||
import type { useRender } from '@base-ui-components/react/use-render';
|
||||
|
||||
@@ -219,6 +218,28 @@ export interface ContainerProps {
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
// @public
|
||||
export const DataTable: {
|
||||
Root: ForwardRefExoticComponent<
|
||||
DataTableRootProps & RefAttributes<HTMLDivElement>
|
||||
>;
|
||||
Pagination: <TData>(
|
||||
props: DataTablePaginationProps<TData> & {
|
||||
ref?: React.ForwardedRef<HTMLDivElement>;
|
||||
},
|
||||
) => React.ReactElement;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DataTablePaginationProps<TData>
|
||||
extends React.HTMLAttributes<HTMLDivElement> {
|
||||
table?: Table_2<TData>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DataTableRootProps
|
||||
extends React.HTMLAttributes<HTMLDivElement> {}
|
||||
|
||||
// @public (undocumented)
|
||||
export type Display = 'none' | 'flex' | 'block' | 'inline';
|
||||
|
||||
@@ -1028,43 +1049,37 @@ export type StylingPropDef = {
|
||||
parseValue?: (value: string) => string | undefined;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export const Table: ForwardRefExoticComponent<
|
||||
HTMLAttributes<HTMLTableElement> & RefAttributes<HTMLTableElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const TableBody: ForwardRefExoticComponent<
|
||||
HTMLAttributes<HTMLTableSectionElement> &
|
||||
RefAttributes<HTMLTableSectionElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const TableCell: ForwardRefExoticComponent<
|
||||
TdHTMLAttributes<HTMLTableCellElement> & RefAttributes<HTMLTableCellElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const TableFooter: ForwardRefExoticComponent<
|
||||
HTMLAttributes<HTMLTableSectionElement> &
|
||||
RefAttributes<HTMLTableSectionElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const TableHead: ForwardRefExoticComponent<
|
||||
ThHTMLAttributes<HTMLTableCellElement> & RefAttributes<HTMLTableCellElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const TableHeader: ForwardRefExoticComponent<
|
||||
HTMLAttributes<HTMLTableSectionElement> &
|
||||
RefAttributes<HTMLTableSectionElement>
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const TableRow: ForwardRefExoticComponent<
|
||||
HTMLAttributes<HTMLTableRowElement> & RefAttributes<HTMLTableRowElement>
|
||||
>;
|
||||
// @public
|
||||
export const Table: {
|
||||
Root: React_2.ForwardRefExoticComponent<
|
||||
React_2.HTMLAttributes<HTMLTableElement> &
|
||||
React_2.RefAttributes<HTMLTableElement>
|
||||
>;
|
||||
Header: React_2.ForwardRefExoticComponent<
|
||||
React_2.HTMLAttributes<HTMLTableSectionElement> &
|
||||
React_2.RefAttributes<HTMLTableSectionElement>
|
||||
>;
|
||||
Body: React_2.ForwardRefExoticComponent<
|
||||
React_2.HTMLAttributes<HTMLTableSectionElement> &
|
||||
React_2.RefAttributes<HTMLTableSectionElement>
|
||||
>;
|
||||
Head: React_2.ForwardRefExoticComponent<
|
||||
React_2.ThHTMLAttributes<HTMLTableCellElement> &
|
||||
React_2.RefAttributes<HTMLTableCellElement>
|
||||
>;
|
||||
Row: React_2.ForwardRefExoticComponent<
|
||||
React_2.HTMLAttributes<HTMLTableRowElement> &
|
||||
React_2.RefAttributes<HTMLTableRowElement>
|
||||
>;
|
||||
Cell: React_2.ForwardRefExoticComponent<
|
||||
React_2.TdHTMLAttributes<HTMLTableCellElement> &
|
||||
React_2.RefAttributes<HTMLTableCellElement>
|
||||
>;
|
||||
Caption: React_2.ForwardRefExoticComponent<
|
||||
React_2.HTMLAttributes<HTMLTableCaptionElement> &
|
||||
React_2.RefAttributes<HTMLTableCaptionElement>
|
||||
>;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
const Text_2: ForwardRefExoticComponent<
|
||||
|
||||
@@ -14,11 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Table } from '../Table';
|
||||
import { DataTable } from '.';
|
||||
import { components } from './mocked-components';
|
||||
import { components, Component } from './mocked-components';
|
||||
import { columns } from './mocked-columns';
|
||||
import {
|
||||
flexRender,
|
||||
@@ -38,7 +37,7 @@ type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
render: () => {
|
||||
const table = useReactTable({
|
||||
const table = useReactTable<Component>({
|
||||
data: components,
|
||||
columns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
@@ -97,16 +96,7 @@ export const Default: Story = {
|
||||
)}
|
||||
</Table.Body>
|
||||
</Table.Root>
|
||||
<DataTable.Pagination
|
||||
pageIndex={table.getState().pagination.pageIndex}
|
||||
pageSize={table.getState().pagination.pageSize}
|
||||
totalRows={table.getRowCount()}
|
||||
onClickPrevious={() => table.previousPage()}
|
||||
onClickNext={() => table.nextPage()}
|
||||
canPrevious={table.getCanPreviousPage()}
|
||||
canNext={table.getCanNextPage()}
|
||||
setPageSize={pageSize => table.setPageSize(pageSize)}
|
||||
/>
|
||||
<DataTable.Pagination table={table} />
|
||||
</DataTable.Root>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { DataTablePagination } from './DataTablePagination';
|
||||
import {
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from '@tanstack/react-table';
|
||||
import { components, Component } from '../mocked-components';
|
||||
import { columns } from '../mocked-columns';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/DataTable/Pagination',
|
||||
@@ -26,14 +35,16 @@ export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
totalRows: 100,
|
||||
onClickPrevious: () => {},
|
||||
onClickNext: () => {},
|
||||
canPrevious: true,
|
||||
canNext: true,
|
||||
setPageSize: () => {},
|
||||
render: () => {
|
||||
const table = useReactTable<Component>({
|
||||
data: components,
|
||||
columns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
});
|
||||
|
||||
return <DataTablePagination table={table} />;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
justify-content: space-between;
|
||||
padding-top: var(--canon-space-3);
|
||||
border-top: 1px solid var(--canon-border);
|
||||
margin-top: var(--canon-space-3);
|
||||
}
|
||||
|
||||
.canon-TablePagination--left {
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import * as React from 'react';
|
||||
|
||||
import { forwardRef } from 'react';
|
||||
import { Text } from '../../Text';
|
||||
import { DataTablePaginationProps } from './types';
|
||||
import { IconButton } from '../../IconButton';
|
||||
@@ -21,25 +22,19 @@ import clsx from 'clsx';
|
||||
import { Select } from '../../Select';
|
||||
|
||||
/** @public */
|
||||
const DataTablePagination = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
DataTablePaginationProps
|
||||
>(({ className, ...props }, ref) => {
|
||||
const {
|
||||
pageIndex,
|
||||
pageSize,
|
||||
onClickPrevious,
|
||||
onClickNext,
|
||||
canPrevious,
|
||||
canNext,
|
||||
totalRows,
|
||||
setPageSize,
|
||||
} = props;
|
||||
function DataTablePagination<TData>(
|
||||
props: DataTablePaginationProps<TData>,
|
||||
ref: React.ForwardedRef<HTMLDivElement>,
|
||||
) {
|
||||
const { className, table, ...rest } = props;
|
||||
const pageIndex = table?.getState().pagination.pageIndex;
|
||||
const pageSize = table?.getState().pagination.pageSize;
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={clsx('canon-TablePagination', className)}
|
||||
{...props}
|
||||
{...rest}
|
||||
>
|
||||
<div className="canon-TablePagination--left">
|
||||
<Select
|
||||
@@ -55,32 +50,37 @@ const DataTablePagination = React.forwardRef<
|
||||
]}
|
||||
value={pageSize?.toString()}
|
||||
onValueChange={value => {
|
||||
setPageSize?.(Number(value));
|
||||
table?.setPageSize(Number(value));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="canon-TablePagination--right">
|
||||
<Text variant="body">{`${(pageIndex ?? 0) * (pageSize ?? 10) + 1} - ${
|
||||
((pageIndex ?? 0) + 1) * (pageSize ?? 10)
|
||||
} of ${totalRows}`}</Text>
|
||||
} of ${table?.getRowCount()}`}</Text>
|
||||
<IconButton
|
||||
variant="secondary"
|
||||
size="small"
|
||||
onClick={onClickPrevious}
|
||||
disabled={!canPrevious}
|
||||
onClick={() => table?.previousPage()}
|
||||
disabled={!table?.getCanPreviousPage()}
|
||||
icon="chevron-left"
|
||||
/>
|
||||
<IconButton
|
||||
variant="secondary"
|
||||
size="small"
|
||||
onClick={onClickNext}
|
||||
disabled={!canNext}
|
||||
onClick={() => table?.nextPage()}
|
||||
disabled={!table?.getCanNextPage()}
|
||||
icon="chevron-right"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
DataTablePagination.displayName = 'DataTablePagination';
|
||||
}
|
||||
|
||||
export { DataTablePagination };
|
||||
const ForwardedDataTablePagination = forwardRef(DataTablePagination) as <TData>(
|
||||
props: DataTablePaginationProps<TData> & {
|
||||
ref?: React.ForwardedRef<HTMLDivElement>;
|
||||
},
|
||||
) => React.ReactElement;
|
||||
|
||||
export { ForwardedDataTablePagination as DataTablePagination };
|
||||
|
||||
@@ -14,39 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Table } from '@tanstack/react-table';
|
||||
|
||||
/** @public */
|
||||
export interface DataTablePaginationProps
|
||||
export interface DataTablePaginationProps<TData>
|
||||
extends React.HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* The current page index.
|
||||
* The table instance.
|
||||
*/
|
||||
pageIndex?: number;
|
||||
/**
|
||||
* The current page size.
|
||||
*/
|
||||
pageSize?: number;
|
||||
/**
|
||||
* The total number of rows.
|
||||
*/
|
||||
totalRows?: number;
|
||||
/**
|
||||
* The function to call when the previous button is clicked.
|
||||
*/
|
||||
onClickPrevious?: () => void;
|
||||
/**
|
||||
* The function to call when the next button is clicked.
|
||||
*/
|
||||
onClickNext?: () => void;
|
||||
/**
|
||||
* Whether the previous button is disabled.
|
||||
*/
|
||||
canPrevious?: boolean;
|
||||
/**
|
||||
* Whether the next button is disabled.
|
||||
*/
|
||||
canNext?: boolean;
|
||||
/**
|
||||
* The function to call when the page size is changed.
|
||||
*/
|
||||
setPageSize?: (pageSize: number) => void;
|
||||
table?: Table<TData>;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { DataTableRoot } from './DataTableRoot';
|
||||
import { DataTablePagination } from '../Pagination/DataTablePagination';
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
|
||||
import { ColumnDef } from '@tanstack/react-table';
|
||||
import { Component } from './mocked-components';
|
||||
import { Checkbox } from '../Checkbox';
|
||||
|
||||
@@ -14,14 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { forwardRef } from 'react';
|
||||
import clsx from 'clsx';
|
||||
|
||||
const TableRoot = forwardRef<
|
||||
HTMLTableElement,
|
||||
React.HTMLAttributes<HTMLTableElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div className="table">
|
||||
<table ref={ref} className={className} {...props} />
|
||||
</div>
|
||||
<table ref={ref} className={clsx('canon-TableRoot', className)} {...props} />
|
||||
));
|
||||
TableRoot.displayName = 'TableRoot';
|
||||
|
||||
@@ -31,7 +30,7 @@ const TableHeader = forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<thead
|
||||
ref={ref}
|
||||
className={['table-header', className].join(' ')}
|
||||
className={clsx('canon-TableHeader', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
@@ -41,7 +40,7 @@ const TableBody = forwardRef<
|
||||
HTMLTableSectionElement,
|
||||
React.HTMLAttributes<HTMLTableSectionElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<tbody ref={ref} className={['table-body', className].join(' ')} {...props} />
|
||||
<tbody ref={ref} className={clsx('canon-TableBody', className)} {...props} />
|
||||
));
|
||||
TableBody.displayName = 'TableBody';
|
||||
|
||||
@@ -49,7 +48,7 @@ const TableRow = forwardRef<
|
||||
HTMLTableRowElement,
|
||||
React.HTMLAttributes<HTMLTableRowElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<tr ref={ref} className={['table-row', className].join(' ')} {...props}>
|
||||
<tr ref={ref} className={clsx('canon-TableRow', className)} {...props}>
|
||||
{props.children}
|
||||
</tr>
|
||||
));
|
||||
@@ -59,7 +58,7 @@ const TableHead = forwardRef<
|
||||
HTMLTableCellElement,
|
||||
React.ThHTMLAttributes<HTMLTableCellElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<th ref={ref} className={['table-head', className].join(' ')} {...props} />
|
||||
<th ref={ref} className={clsx('canon-TableHead', className)} {...props} />
|
||||
));
|
||||
TableHead.displayName = 'TableHead';
|
||||
|
||||
@@ -67,7 +66,7 @@ const TableCell = forwardRef<
|
||||
HTMLTableCellElement,
|
||||
React.TdHTMLAttributes<HTMLTableCellElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<td ref={ref} className={['table-cell', className].join(' ')} {...props} />
|
||||
<td ref={ref} className={clsx('canon-TableCell', className)} {...props} />
|
||||
));
|
||||
TableCell.displayName = 'TableCell';
|
||||
|
||||
@@ -77,7 +76,7 @@ const TableCaption = forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<caption
|
||||
ref={ref}
|
||||
className={['table-caption', className].join(' ')}
|
||||
className={clsx('canon-TableCaption', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
@@ -1,54 +1,31 @@
|
||||
.table {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
.canon-TableRoot {
|
||||
width: 100%;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
caption-side: bottom;
|
||||
font-size: var(--canon-font-size-sm);
|
||||
border-collapse: collapse;
|
||||
}
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.table-head {
|
||||
.canon-TableHead {
|
||||
text-align: left;
|
||||
padding: var(--canon-space-3);
|
||||
font-size: var(--canon-font-size-3);
|
||||
}
|
||||
|
||||
.table-body {
|
||||
.canon-TableBody {
|
||||
tr:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.table-row {
|
||||
.canon-TableRow {
|
||||
border-bottom: 1px solid var(--canon-border);
|
||||
transition: color 0.2s ease-in-out;
|
||||
|
||||
&:hover td {
|
||||
background-color: var(--canon-bg-tint);
|
||||
}
|
||||
|
||||
& .table-cell:first-child {
|
||||
border-top-left-radius: var(--canon-radius-2);
|
||||
border-bottom-left-radius: var(--canon-radius-2);
|
||||
box-shadow: inset 4px 2px 0 0 var(--canon-bg-surface-1),
|
||||
inset 4px -2px 0 0 var(--canon-bg-surface-1);
|
||||
padding-left: var(--canon-space-3);
|
||||
}
|
||||
|
||||
& .table-cell:last-child {
|
||||
border-top-right-radius: var(--canon-radius-2);
|
||||
border-bottom-right-radius: var(--canon-radius-2);
|
||||
box-shadow: inset -4px 2px 0 0 var(--canon-bg-surface-1),
|
||||
inset -4px -2px 0 0 var(--canon-bg-surface-1);
|
||||
padding-right: var(--canon-space-3);
|
||||
&:hover {
|
||||
background-color: var(--canon-bg-tint-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.table-cell {
|
||||
.canon-TableCell {
|
||||
padding: var(--canon-space-3);
|
||||
background-color: var(--canon-bg);
|
||||
box-shadow: inset 0px 2px 0 0 var(--canon-bg-surface-1),
|
||||
inset 0px -2px 0 0 var(--canon-bg-surface-1);
|
||||
font-size: var(--canon-font-size-3);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user