add collapsible table

This commit is contained in:
Aleka Cheung 2024-01-12 15:37:08 -05:00
parent e93850484b
commit ef5b5013c5
No known key found for this signature in database
GPG Key ID: 53E472E5EF4F4102
4 changed files with 112 additions and 9 deletions

View File

@ -0,0 +1,91 @@
import { Key, useState } from 'react';
import styled, { type AnyStyledComponent, css } from 'styled-components';
import { STRING_KEYS } from '@/constants/localization';
import { useStringGetter } from '@/hooks';
import { CaretIcon } from '@/icons';
import { Button } from './Button';
import {
Table,
type ElementProps as TableElementProps,
type StyleProps as TableStyleProps,
} from './Table';
type CollapsibleTableAdditionalProps = {
initialNumRowsToShow: number;
};
type CollapsibleTableProps<
TableRowData extends object,
TableRowKey extends Key
> = TableElementProps<TableRowData, TableRowKey> &
TableStyleProps &
CollapsibleTableAdditionalProps;
export const CollapsibleTable = <TableRowData extends object, TableRowKey extends Key>({
data = [],
initialNumRowsToShow,
className,
...tableProps
}: CollapsibleTableProps<TableRowData, TableRowKey>) => {
const [numRowsToShow, setNumRowsToShow] = useState(initialNumRowsToShow);
const stringGetter = useStringGetter();
const showViewMoreButton = numRowsToShow !== undefined && numRowsToShow < data.length;
return (
<Styled.Container>
<Styled.Table
{...tableProps}
data={data}
numRowsToShow={numRowsToShow}
showViewMoreButton={showViewMoreButton}
className={className}
/>
{showViewMoreButton && (
<Styled.ViewMoreButton
onClick={() => setNumRowsToShow(data.length)}
slotRight={<CaretIcon />}
>
{stringGetter({ key: STRING_KEYS.VIEW_MORE })}
</Styled.ViewMoreButton>
)}
</Styled.Container>
);
};
const Styled: Record<string, AnyStyledComponent> = {};
Styled.Container = styled.div`
display: grid;
grid-template-areas: 'table' 'viewmore';
grid-template-rows: auto 1fr;
`;
Styled.Table = styled(Table)<{ showViewMoreButton?: boolean }>`
grid-area: table;
${({ showViewMoreButton }) =>
showViewMoreButton &&
css`
table tbody tr:last-of-type {
box-shadow: 0 calc(-1 * var(--border-width)) 0 0 var(--border-color);
}
`}
`;
Styled.ViewMoreButton = styled(Button)`
--button-backgroundColor: var(--color-layer-2);
--button-textColor: var(--color-text-1);
width: 100%;
grid-area: viewmore;
svg {
width: 0.675rem;
margin-left: 0.5ch;
}
`;

View File

@ -11,6 +11,5 @@ export const DetachedScrollableSection = styled.section`
export const AttachedExpandingSection = styled.section`
${layoutMixins.contentSectionAttached}
${layoutMixins.expandingColumnWithHeader}
gap: var(--border-width);
`;

View File

@ -36,8 +36,6 @@ import { useAsyncList } from 'react-stately';
import { useBreakpoints } from '@/hooks';
import { MediaQueryKeys } from '@/hooks/useBreakpoints';
import { Checkbox } from '@/components/Checkbox';
import { breakpoints } from '@/styles';
import { layoutMixins } from '@/styles/layoutMixins';
@ -80,7 +78,7 @@ export type ColumnDef<TableRowData extends object> = {
width?: ColumnSize;
};
type ElementProps<TableRowData extends object | CustomRowConfig, TableRowKey extends Key> = {
export type ElementProps<TableRowData extends object | CustomRowConfig, TableRowKey extends Key> = {
label?: string;
columns: ColumnDef<TableRowData>[];
data: TableRowData[];
@ -92,11 +90,12 @@ type ElementProps<TableRowData extends object | CustomRowConfig, TableRowKey ext
selectionBehavior?: 'replace' | 'toggle';
onRowAction?: (key: TableRowKey, row: TableRowData) => void;
slotEmpty?: React.ReactNode;
numRowsToShow?: number;
// collection: TableCollection<string>;
// children: React.ReactNode;
};
type StyleProps = {
export type StyleProps = {
hideHeader?: boolean;
withGradientCardRows?: boolean;
withFocusStickyRows?: boolean;
@ -121,6 +120,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
selectionMode = 'single',
selectionBehavior = 'toggle',
slotEmpty,
numRowsToShow = data.length,
// shouldRowRender,
// collection,
@ -233,7 +233,7 @@ export const Table = <TableRowData extends object, TableRowKey extends Key>({
)}
</TableHeader>
<TableBody items={list.items}>
<TableBody items={list.items.slice(0, numRowsToShow)}>
{(item) => (
<Row key={getRowKey(item)}>
{(columnKey) => (
@ -337,6 +337,7 @@ const TableRoot = <TableRowData extends object | CustomRowConfig, TableRowKey ex
<TableBodyRowGroup
withGradientCardRows={props.withGradientCardRows}
withInnerBorders={props.withInnerBorders}
withOuterBorder={props.withOuterBorder}
>
{/* {Array.from(collection.getChildren!(collection.body.key), (row) => */}
{[...collection.body.childNodes].map((row) =>
@ -415,6 +416,7 @@ const TableBodyRowGroup = ({
children,
withGradientCardRows,
withInnerBorders,
withOuterBorder,
}: { children: React.ReactNode } & StyleProps) => {
const { rowGroupProps } = useTableRowGroup();
@ -423,6 +425,7 @@ const TableBodyRowGroup = ({
{...rowGroupProps}
withGradientCardRows={withGradientCardRows}
withInnerBorders={withInnerBorders}
withOuterBorder={withOuterBorder}
>
{children}
</Styled.Tbody>
@ -660,7 +663,7 @@ Styled.Empty = styled.div<{ withOuterBorder: boolean }>`
justify-items: center;
align-content: center;
padding: 2rem;
padding: 4rem;
gap: 0.75em;
color: var(--color-text-0);
@ -868,6 +871,18 @@ Styled.Tbody = styled.tbody<StyleProps>`
--stickyArea2-paddingLeft: var(--border-width);
--stickyArea2-paddingRight: var(--border-width);
tr:first-of-type {
box-shadow: 0 calc(var(--border-width)) 0 0 var(--border-color);
}
`}
${({ withOuterBorder }) =>
withOuterBorder &&
css`
tr:last-of-type:not(:only-of-type) {
box-shadow: 0 calc(-1 * var(--border-width)) 0 0 var(--border-color);
}
tr:first-of-type {
box-shadow: none;
}

View File

@ -36,8 +36,6 @@ import { openDialog } from '@/state/dialogs';
import { MustBigNumber } from '@/lib/numbers';
import { getHydratedTradingData } from '@/lib/orders';
import { tableMixins } from '@/styles/tableMixins';
import { breakpoints } from '@/styles';
const MOBILE_FILLS_PER_PAGE = 50;