From cd30c9c7d924cab561b5cf3add171dea51292985 Mon Sep 17 00:00:00 2001 From: aleka Date: Wed, 24 Jan 2024 12:26:32 -0500 Subject: [PATCH] add collapsible table (#231) * add collapsible table * update to add a TR inside table instead --- src/components/ContentSection.tsx | 1 - src/components/Table.tsx | 79 +++++++++++++++++++++++++++---- src/views/tables/FillsTable.tsx | 2 - 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/src/components/ContentSection.tsx b/src/components/ContentSection.tsx index 3723841..7aa265f 100644 --- a/src/components/ContentSection.tsx +++ b/src/components/ContentSection.tsx @@ -11,6 +11,5 @@ export const DetachedScrollableSection = styled.section` export const AttachedExpandingSection = styled.section` ${layoutMixins.contentSectionAttached} - ${layoutMixins.expandingColumnWithHeader} gap: var(--border-width); `; diff --git a/src/components/Table.tsx b/src/components/Table.tsx index d82a94a..36f9283 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -33,17 +33,20 @@ import { import { useAsyncList } from 'react-stately'; -import { useBreakpoints } from '@/hooks'; +import { useBreakpoints, useStringGetter } from '@/hooks'; import { MediaQueryKeys } from '@/hooks/useBreakpoints'; -import { Checkbox } from '@/components/Checkbox'; - import { breakpoints } from '@/styles'; import { layoutMixins } from '@/styles/layoutMixins'; +import { CaretIcon } from '@/icons'; + +import { STRING_KEYS } from '@/constants/localization'; + +import { MustBigNumber } from '@/lib/numbers'; import { Icon, IconName } from './Icon'; import { Tag } from './Tag'; -import { MustBigNumber } from '@/lib/numbers'; +import { Button } from './Button'; export { TableCell } from './Table/TableCell'; export { TableColumnHeader } from './Table/TableColumnHeader'; @@ -65,7 +68,7 @@ export type TableItem = { onSelect?: (key: TableRowData) => void; }; -export type ColumnDef = { +type ColumnDef = { columnKey: string; label: React.ReactNode; tag?: React.ReactNode; @@ -80,7 +83,7 @@ export type ColumnDef = { width?: ColumnSize; }; -type ElementProps = { +export type ElementProps = { label?: string; columns: ColumnDef[]; data: TableRowData[]; @@ -92,6 +95,7 @@ type ElementProps void; slotEmpty?: React.ReactNode; + initialNumRowsToShow?: number; // collection: TableCollection; // children: React.ReactNode; }; @@ -121,6 +125,7 @@ export const Table = ({ selectionMode = 'single', selectionBehavior = 'toggle', slotEmpty, + initialNumRowsToShow = data.length, // shouldRowRender, // collection, @@ -136,6 +141,7 @@ export const Table = ({ style, }: ElementProps & StyleProps) => { const [selectedKeys, setSelectedKeys] = useState(new Set()); + const [numRowsToShow, setNumRowsToShow] = useState(initialNumRowsToShow); const currentBreakpoints = useBreakpoints(); const shownColumns = columns.filter( @@ -209,6 +215,12 @@ export const Table = ({ onRowAction && ((key: TableRowKey) => onRowAction(key, data.find((row) => getRowKey(row) === key)!)) } + numColumns={shownColumns.length} + onViewMoreClick={ + numRowsToShow !== undefined && numRowsToShow < data.length + ? () => setNumRowsToShow(data.length) + : undefined + } // shouldRowRender={shouldRowRender} hideHeader={hideHeader} withGradientCardRows={withGradientCardRows} @@ -233,7 +245,7 @@ export const Table = ({ )} - + {(item) => ( {(columnKey) => ( @@ -267,6 +279,8 @@ const TableRoot = void; // shouldRowRender?: (prevRowData: object, currentRowData: object) => boolean; children: CollectionChildren; + numColumns: number; + onViewMoreClick?: () => void; hideHeader?: boolean; withGradientCardRows?: boolean; @@ -276,7 +290,7 @@ const TableRoot = { - const { selectionMode, selectionBehavior } = props; + const { selectionMode, selectionBehavior, numColumns, onViewMoreClick } = props; const state = useTableState({ ...props, @@ -337,6 +351,7 @@ const TableRoot = {/* {Array.from(collection.getChildren!(collection.body.key), (row) => */} {[...collection.body.childNodes].map((row) => @@ -382,6 +397,9 @@ const TableRoot = ) )} + {onViewMoreClick ? ( + + ) : undefined} ); @@ -415,6 +433,7 @@ const TableBodyRowGroup = ({ children, withGradientCardRows, withInnerBorders, + withOuterBorder, }: { children: React.ReactNode } & StyleProps) => { const { rowGroupProps } = useTableRowGroup(); @@ -423,6 +442,7 @@ const TableBodyRowGroup = ({ {...rowGroupProps} withGradientCardRows={withGradientCardRows} withInnerBorders={withInnerBorders} + withOuterBorder={withOuterBorder} > {children} @@ -489,6 +509,23 @@ const TableColumnHeader = ({ ); }; +export const ViewMoreRow = ({ colSpan, onClick }: { colSpan: number; onClick: () => void }) => { + const stringGetter = useStringGetter(); + return ( + + e.preventDefault()} + onPointerDown={(e: MouseEvent) => e.preventDefault()} + > + } onClick={onClick}> + {stringGetter({ key: STRING_KEYS.VIEW_MORE })} + + + + ); +}; + export const TableRow = ({ item, children, @@ -660,7 +697,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 +905,18 @@ Styled.Tbody = styled.tbody` --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; } @@ -922,3 +971,15 @@ Styled.Row = styled.div` ${layoutMixins.inlineRow} padding: var(--tableCell-padding); `; + +Styled.ViewMoreButton = styled(Button)` + --button-backgroundColor: var(--color-layer-2); + --button-textColor: var(--color-text-1); + + width: 100%; + + svg { + width: 0.675rem; + margin-left: 0.5ch; + } +`; diff --git a/src/views/tables/FillsTable.tsx b/src/views/tables/FillsTable.tsx index 084d5d9..4a32c1c 100644 --- a/src/views/tables/FillsTable.tsx +++ b/src/views/tables/FillsTable.tsx @@ -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;