Skip to content

Commit

Permalink
feat(Table): footer (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
beliarh authored Jul 24, 2024
1 parent 3360374 commit 484954c
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 12 deletions.
31 changes: 31 additions & 0 deletions src/components/FooterCell/FooterCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';

import type {Header} from '@tanstack/react-table';
import {flexRender} from '@tanstack/react-table';

import {getCellStyles, getHeaderCellClassModes} from '../../utils';
import {b} from '../Table/Table.classname';

export interface FooterCellProps<TData, TValue> {
className?: string;
header: Header<TData, TValue>;
}

export const FooterCell = <TData, TValue>({className, header}: FooterCellProps<TData, TValue>) => {
if (header.isPlaceholder) {
return null;
}

const rowSpan = header.depth - header.column.depth;

return (
<th
className={b('footer-cell', getHeaderCellClassModes(header), className)}
colSpan={header.colSpan > 1 ? header.colSpan : undefined}
rowSpan={rowSpan > 1 ? rowSpan : undefined}
style={getCellStyles(header)}
>
{flexRender(header.column.columnDef.footer, header.getContext())}
</th>
);
};
1 change: 1 addition & 0 deletions src/components/FooterCell/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './FooterCell';
33 changes: 33 additions & 0 deletions src/components/FooterRow/FooterRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';

import type {HeaderGroup} from '@tanstack/react-table';

import type {FooterCellProps} from '../FooterCell';
import {FooterCell} from '../FooterCell';
import {b} from '../Table/Table.classname';

export interface FooterRowProps<TData, TValue> {
cellClassName: FooterCellProps<TData, TValue>['className'];
className?: string;
footerGroup: HeaderGroup<TData>;
}

export const FooterRow = <TData, TValue>({
cellClassName,
className,
footerGroup,
}: FooterRowProps<TData, TValue>) => {
const isEmptyRow = footerGroup.headers.every((header) => !header.column.columnDef.footer);

if (isEmptyRow) {
return null;
}

return (
<tr className={b('footer-row', className)}>
{footerGroup.headers.map((header) => (
<FooterCell key={header.column.id} className={cellClassName} header={header} />
))}
</tr>
);
};
1 change: 1 addition & 0 deletions src/components/FooterRow/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './FooterRow';
29 changes: 20 additions & 9 deletions src/components/Table/Table.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,17 @@ $block: '.#{variables.$ns}table';
}
}

&__footer {
&_sticky {
position: sticky;
inset-block-end: 0;
z-index: 1;
}
}

&__cell,
&__header-cell {
&__header-cell,
&__footer-cell {
height: inherit;

text-align: start;
Expand All @@ -36,11 +45,14 @@ $block: '.#{variables.$ns}table';
font-weight: normal;
}

&__header-cell {
&__header-cell,
&__footer-cell {
position: relative;

font-weight: 500;
}

&__header-cell {
&_sortable {
cursor: pointer;
user-select: none;
Expand All @@ -60,15 +72,13 @@ $block: '.#{variables.$ns}table';
position: relative;
}

&__header {
&__header,
&__footer {
display: grid;

inset-block-start: 0;

z-index: 1;
}

&__header-row {
&__header-row,
&__footer-row {
display: flex;

width: 100%;
Expand All @@ -85,7 +95,8 @@ $block: '.#{variables.$ns}table';
}

&__cell,
&__header-cell {
&__header-cell,
&__footer-cell {
display: flex;
}
}
Expand Down
30 changes: 27 additions & 3 deletions src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {Row as RowType, Table as TableType} from '@tanstack/react-table';
import type {VirtualItem, Virtualizer} from '@tanstack/react-virtual';

import {DraggableRow} from '../DraggableRow';
import {FooterRow} from '../FooterRow';
import type {HeaderRowProps} from '../HeaderRow';
import {HeaderRow} from '../HeaderRow';
import {Row} from '../Row';
Expand All @@ -21,6 +22,9 @@ export interface TableProps<TData, TScrollElement extends Element | Window = HTM
cellClassName?: string;
className?: string;
enableNesting?: boolean;
footerCellClassName?: string;
footerClassName?: string;
footerRowClassName?: string;
getGroupTitle?: RowProps<TData>['getGroupTitle'];
getIsCustomRow?: RowProps<TData>['getIsCustomRow'];
getIsGroupHeaderRow?: RowProps<TData>['getIsGroupHeaderRow'];
Expand All @@ -39,8 +43,10 @@ export interface TableProps<TData, TScrollElement extends Element | Window = HTM
rowClassName?: string;
rowVirtualizer?: Virtualizer<TScrollElement, HTMLTableRowElement>;
sortIndicatorClassName?: HeaderRowProps<TData, unknown>['sortIndicatorClassName'];
stickyFooter?: boolean;
stickyHeader?: boolean;
table: TableType<TData>;
withFooter?: boolean;
withHeader?: boolean;
}

Expand All @@ -51,6 +57,9 @@ export const Table = React.forwardRef(
cellClassName,
className,
enableNesting,
footerCellClassName,
footerClassName,
footerRowClassName,
getGroupTitle,
getIsGroupHeaderRow,
getRowAttributes,
Expand All @@ -66,8 +75,10 @@ export const Table = React.forwardRef(
rowClassName,
rowVirtualizer,
sortIndicatorClassName,
stickyHeader = false,
stickyFooter,
stickyHeader,
table,
withFooter,
withHeader = true,
}: TableProps<TData, TScrollElement>,
ref: React.Ref<HTMLTableElement>,
Expand All @@ -84,7 +95,8 @@ export const Table = React.forwardRef(

const {rows} = table.getRowModel();

const headerGroups = table.getHeaderGroups();
const headerGroups = withHeader && table.getHeaderGroups();
const footerGroups = withFooter && table.getFooterGroups();

return (
<TableContextProvider getRowByIndex={getRowByIndex} enableNesting={enableNesting}>
Expand All @@ -93,7 +105,7 @@ export const Table = React.forwardRef(
className={b({'with-row-virtualization': Boolean(rowVirtualizer)}, className)}
data-dragging-row-index={draggingRowIndex > -1 ? draggingRowIndex : undefined}
>
{withHeader && (
{headerGroups && (
<thead className={b('header', {sticky: stickyHeader}, headerClassName)}>
{headerGroups.map((headerGroup, index) => (
<HeaderRow
Expand Down Expand Up @@ -144,6 +156,18 @@ export const Table = React.forwardRef(
return <Row key={row.id} {...rowProps} />;
})}
</tbody>
{footerGroups && (
<tfoot className={b('footer', {sticky: stickyFooter}, footerClassName)}>
{footerGroups.map((footerGroup) => (
<FooterRow
key={footerGroup.id}
cellClassName={footerCellClassName}
className={footerRowClassName}
footerGroup={footerGroup}
/>
))}
</tfoot>
)}
</table>
</TableContextProvider>
);
Expand Down
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './Cell';
export * from './DragHandle';
export * from './DraggableRow';
export * from './DraggableRowMarker';
export * from './FooterCell';
export * from './GroupHeader';
export * from './HeaderCell';
export * from './HeaderRow';
Expand Down

0 comments on commit 484954c

Please sign in to comment.