Skip to content

Commit 7108dec

Browse files
Merge pull request #804 from buildo/table_footers
Allow Table columns to have footers
2 parents 502ddee + 7e48a62 commit 7108dec

File tree

6 files changed

+108
-0
lines changed

6 files changed

+108
-0
lines changed

packages/bento-design-system/src/Table/Config.ts

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export type TableConfig = {
1313
emptyIcon: (props: IconProps) => JSX.Element;
1414
headerBackgroundColor: BentoSprinkles["background"];
1515
headerForegroundColor: BentoSprinkles["color"];
16+
footerBackgroundColor: BentoSprinkles["background"];
17+
footerForegroundColor: BentoSprinkles["color"];
1618
hintPlacement: TooltipPlacement;
1719
cellTooltipPlacement: TooltipPlacement;
1820
evenRowsBackgroundColor: BentoSprinkles["background"];
@@ -22,6 +24,7 @@ export type TableConfig = {
2224
selectedRowBackgroundColor: keyof typeof vars.backgroundColor;
2325
padding: {
2426
header: CellPaddingConfig;
27+
footer: CellPaddingConfig;
2528
defaultCell: CellPaddingConfig;
2629
buttonCell: CellPaddingConfig | undefined;
2730
buttonLinkCell: CellPaddingConfig | undefined;

packages/bento-design-system/src/Table/Table.css.ts

+22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { createVar, style } from "@vanilla-extract/css";
22
import { bentoSprinkles } from "../internal";
33
import { strictRecipe } from "../util/strictRecipe";
4+
import { vars } from "../vars.css";
45

56
export const table = style({
67
gridAutoRows: "max-content",
@@ -21,6 +22,18 @@ export const columnHeader = bentoSprinkles({
2122
height: "full",
2223
});
2324

25+
export const columnFooter = style([
26+
{
27+
boxShadow: `inset 0px 1px 0px ${vars.outlineColor.outlineDecorative}`,
28+
},
29+
bentoSprinkles({
30+
display: "flex",
31+
flexDirection: "column",
32+
justifyContent: "center",
33+
height: "full",
34+
}),
35+
]);
36+
2437
export const sortIconContainer = style({
2538
filter: "opacity(80%)",
2639
});
@@ -36,6 +49,15 @@ export const stickyColumnHeader = style([
3649
}),
3750
]);
3851

52+
export const stickyColumnFooter = style([
53+
{
54+
bottom: 0,
55+
},
56+
bentoSprinkles({
57+
position: "sticky",
58+
}),
59+
]);
60+
3961
export const rowContainer = style({
4062
// NOTE(gabro): this allows us to use the entire row as a parent selector,
4163
// for applying a hover effect on all of its children or clicking on row,

packages/bento-design-system/src/Table/Table.tsx

+77
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ import {
3131
} from "..";
3232
import {
3333
cellContainerRecipe,
34+
columnFooter,
3435
columnHeader,
3536
lastLeftStickyColumn,
3637
rowContainer,
3738
sectionHeader,
3839
sectionHeaderContainer,
3940
selectedRowBackgroundColor,
4041
sortIconContainer,
42+
stickyColumnFooter,
4143
stickyColumnHeader,
4244
stickyTopHeight,
4345
table,
@@ -104,6 +106,7 @@ type Props<
104106
noResultsFeedbackSize?: FeedbackProps["size"];
105107
initialSorting?: Array<SortingRule<C>>;
106108
stickyHeaders?: boolean;
109+
stickyFooters?: boolean;
107110
height?: { custom: string | number };
108111
onRowPress?: (row: Row<RowType<C>>) => void;
109112
virtualizeRows?: boolean | { estimateRowHeight: (index: number) => number };
@@ -143,6 +146,7 @@ export function Table<
143146
onSort,
144147
initialSorting,
145148
stickyHeaders,
149+
stickyFooters = true,
146150
height,
147151
onRowPress,
148152
virtualizeRows: virtualizeRowsConfig,
@@ -417,6 +421,8 @@ export function Table<
417421
}
418422
});
419423

424+
const hasFooters = headerGroups.at(-1)?.headers.some((h) => h.Footer);
425+
420426
return (
421427
<Box
422428
{...getTableProps()}
@@ -459,6 +465,25 @@ export function Table<
459465
{paddingTopRow}
460466
{renderedRows}
461467
{paddingBottomRow}
468+
{hasFooters &&
469+
headerGroups.at(-1)?.headers.map((header, index) => (
470+
<ColumnFooter
471+
column={header}
472+
key={header.id}
473+
style={{
474+
...stickyLeftColumnStyle[header.id],
475+
}}
476+
lastLeftSticky={
477+
header.columns
478+
? header.id === stickyLeftColumnGroupsIds.at(-1)
479+
: index === lastStickyColumnIndex
480+
}
481+
stickyFooters={stickyFooters}
482+
sticky={stickyLeftColumnsIds.includes(header.id)}
483+
first={index === 0}
484+
last={index + 1 === flatColumns.length}
485+
/>
486+
))}
462487
</Box>
463488
);
464489
}
@@ -593,6 +618,58 @@ function ColumnHeader<D extends Record<string, unknown>>({
593618
);
594619
}
595620

621+
function ColumnFooter<D extends Record<string, unknown>>({
622+
column,
623+
style,
624+
lastLeftSticky,
625+
stickyFooters,
626+
sticky,
627+
first,
628+
last,
629+
}: {
630+
column: ColumnInstance<D> | HeaderGroup<D>;
631+
style: CSSProperties;
632+
lastLeftSticky: boolean;
633+
stickyFooters: boolean;
634+
sticky: boolean;
635+
first: boolean;
636+
last: boolean;
637+
}) {
638+
const config = useBentoConfig().table;
639+
640+
return (
641+
<Box
642+
className={[lastLeftSticky && lastLeftStickyColumn, stickyFooters && stickyColumnFooter]}
643+
style={{
644+
...style,
645+
zIndex: sticky ? zIndexes.leftStickyHeader : zIndexes.header,
646+
}}
647+
>
648+
<Box
649+
className={columnFooter}
650+
background={config.footerBackgroundColor}
651+
color={config.footerForegroundColor}
652+
{...column.getFooterProps()}
653+
textAlign={column.align}
654+
{...config.padding.footer}
655+
>
656+
{column.Footer && (
657+
<Box
658+
paddingLeft={first ? config.boundaryPadding : undefined}
659+
paddingRight={last ? config.boundaryPadding : undefined}
660+
>
661+
<Columns space={8} alignY="center" align={column.align}>
662+
<Column width="content">
663+
<Label size="large">{column.render("Footer") as any}</Label>
664+
</Column>
665+
</Columns>
666+
</Box>
667+
)}
668+
</Box>
669+
</Box>
670+
);
671+
}
672+
596673
function SectionHeader({
597674
label,
598675
numberOfStickyColumns,

packages/bento-design-system/src/Table/tableColumn.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export function custom<A extends string, V, D extends Record<string, unknown>>({
3939
sortType,
4040
missingValue,
4141
width,
42+
footer,
4243
...options
4344
}: ColumnOptionsBase<A> & {
4445
Cell: (props: CellProps<D, V>) => Children;
@@ -62,6 +63,7 @@ export function custom<A extends string, V, D extends Record<string, unknown>>({
6263
}
6364
},
6465
Header: headerLabel,
66+
Footer: footer,
6567
} as Column<A, D, V>;
6668

6769
if (sortType) {

packages/bento-design-system/src/Table/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ declare module "react-table" {
1515
sticky?: "left";
1616
gridWidth?: GridWidth;
1717
hint?: LocalizedString | { onPress: () => void };
18+
footer?: string | ((props: { rows: Row<D>[] }) => string);
1819
}
1920

2021
interface ColumnInstance<D extends object>

packages/bento-design-system/src/util/defaultConfigs.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -506,12 +506,15 @@ export const table: TableConfig = {
506506
emptyIcon: IconSearch,
507507
headerBackgroundColor: "backgroundPrimary",
508508
headerForegroundColor: "foregroundPrimary",
509+
footerBackgroundColor: "backgroundPrimary",
510+
footerForegroundColor: "foregroundPrimary",
509511
hintPlacement: "top",
510512
cellTooltipPlacement: "bottom",
511513
evenRowsBackgroundColor: "backgroundSecondary",
512514
selectedRowBackgroundColor: "backgroundInteractiveOverlay",
513515
padding: {
514516
header: { paddingX: 16, paddingY: 8 },
517+
footer: { paddingX: 16, paddingY: 8 },
515518
defaultCell: { paddingX: 16, paddingY: 16 },
516519
buttonCell: { paddingX: 8, paddingY: 8 },
517520
buttonLinkCell: { paddingX: 8, paddingY: 8 },

0 commit comments

Comments
 (0)