Skip to content

Commit

Permalink
fix: add a key prop for the table column
Browse files Browse the repository at this point in the history
This change allows the user to pass a key prop when a dataKey is not applicable for that given column. This could be used for columns that compose data from multiple columns, actions, or decorative columns.

Similar to the dataKey, The key needs to be unique.

Fixes #1292
  • Loading branch information
haideralsh committed Nov 1, 2023
1 parent 511e016 commit 6f3c100
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 31 deletions.
5 changes: 3 additions & 2 deletions src/Table/BaseTable.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { boolean, text } from "@storybook/addon-knobs";
import { action } from "@storybook/addon-actions";
import { Box, DropdownButton, DropdownMenu, Button, Text } from "..";
import { getMockRows, mockColumns } from "./Table.mock-utils";
import { Columns } from "./Table.types";
import { Table } from ".";

const dateToString = ({ cellData }) => {
Expand All @@ -29,7 +30,7 @@ const dropdownCellRenderer = ({ cellData }) => (
</Box>
);

const columns = [
const columns: Columns = [
{ label: "Date", dataKey: "date" },
{ label: "Expected Quantity", dataKey: "expectedQuantity" },
{ label: "Actual Quantity", dataKey: "actualQuantity", align: "right" },
Expand Down Expand Up @@ -183,7 +184,7 @@ const columnsWithFormatter = [
{ label: "Actual Quantity", dataKey: "actualQuantity" },
];

const columnsWithAlignment = [
const columnsWithAlignment: Columns = [
{ label: "Date", dataKey: "date" },
{ label: "Expected Eaches", dataKey: "expectedQuantity" },
{ label: "Actual Eaches", dataKey: "actualQuantity", align: "right" },
Expand Down
4 changes: 2 additions & 2 deletions src/Table/BaseTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import propTypes from "@styled-system/prop-types";
import TableHead from "./TableHead";
import TableBody from "./TableBody";
import TableFoot from "./TableFoot";
import { rowsPropType, ColumnType, RowType } from "./Table.types";
import { rowsPropType, RowType, Columns } from "./Table.types";

export type BaseTableProps = {
columns: ColumnType[];
columns: Columns;
rows: RowType[];
noRowsContent?: string;
keyField?: string;
Expand Down
3 changes: 1 addition & 2 deletions src/Table/Table.story.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable react/prop-types */
import React from "react";
import { action } from "@storybook/addon-actions";
import { boolean, number } from "@storybook/addon-knobs";
Expand Down Expand Up @@ -50,7 +49,7 @@ const columnsWithEverything = [
{ label: "Note", dataKey: "note", width: "45%" },
{
label: "",
dataKey: "actions",
key: "actions",
width: "5%",
cellRenderer: dropdownCellRenderer,
},
Expand Down
33 changes: 19 additions & 14 deletions src/Table/Table.types.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
import { Key, CSSProperties } from "react";
import PropTypes from "prop-types";

export type RowType = any;
export type RowType = unknown;

export type CellInfoType = {
cellData: any;
cellData: unknown;
column: ColumnType;
row: RowType;
};

type ColumnInfoType = {
align?: string;
align?: ColumnAlignment;
label: string;
dataKey?: string;
width?: string;
dataKey?: Key;
width?: string | number;
};

type ColumnAlignment = "left" | "right" | "center";

export type ColumnType = {
align?: string;
align?: ColumnAlignment;
label?: string;
dataKey?: string;
cellFormatter?: (cell: CellInfoType) => React.ReactNode | JSX.Element;
cellRenderer?: (cell: CellInfoType) => React.ReactNode | JSX.Element;
headerRenderer?: (column: ColumnInfoType) => React.ReactNode | JSX.Element;
headerFormatter?: (column: ColumnInfoType) => React.ReactNode | JSX.Element;
width?: string;
};
cellFormatter?: (cell: CellInfoType) => React.ReactNode;
cellRenderer?: (cell: CellInfoType) => React.ReactNode;
headerRenderer?: (column: ColumnInfoType) => React.ReactNode;
headerFormatter?: (column: ColumnInfoType) => React.ReactNode;
width?: string | number;
} & ({ key: Key; dataKey?: never | undefined } | { dataKey: Key; key?: never | undefined });

export type Columns = ColumnType[];

export const columnPropType = PropTypes.shape({
align: PropTypes.oneOf(["right", "left", "center"]),
label: PropTypes.string,
dataKey: PropTypes.string,
dataKey: PropTypes.oneOf([PropTypes.string, PropTypes.number]),
key: PropTypes.oneOf([PropTypes.string, PropTypes.number]),
cellFormatter: PropTypes.func,
cellRenderer: PropTypes.func,
headerRenderer: PropTypes.func,
Expand Down
12 changes: 9 additions & 3 deletions src/Table/TableBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
import { Box } from "../Box";
import { DefaultNDSThemeType } from "../theme.type";
import { rowsPropType, columnsPropType, rowPropType } from "./Table.types";
import TableCell from "./TableCell";
import { DefaultNDSThemeType } from "../theme.type";

const StyledMessageContainer = styled(Box)(({ theme }) => ({
padding: `${theme.space.x3} 0`,
Expand Down Expand Up @@ -64,8 +64,14 @@ const TableBodyRow = ({
onMouseEnter,
}: TableBodyRowProps) => {
const renderAllCells = () =>
columns.map((column) => (
<TableCell key={column.dataKey} row={row} column={column} cellData={row[column.dataKey]} compact={compact} />
columns.map((column, index) => (
<TableCell
key={column.dataKey ?? column.key ?? index}
row={row}
column={column}
cellData={row[column.dataKey]}
compact={compact}
/>
));
return (
<>
Expand Down
20 changes: 15 additions & 5 deletions src/Table/TableFoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from "prop-types";
import styled from "styled-components";
import TableCell from "./TableCell";
import StyledTh from "./StyledTh";
import { columnsPropType, rowsPropType, rowPropType } from "./Table.types";
import { columnsPropType, rowsPropType, rowPropType, RowType, Columns } from "./Table.types";

const StyledFooterRow = styled.tr(({ theme }) => ({
"&:first-of-type": {
Expand Down Expand Up @@ -31,7 +31,7 @@ const TableFooterRow = ({ row, columns, loading, compact }) => {
) : (
!loading && (
<TableCell
key={column.dataKey}
key={column.dataKey ?? column.key ?? index}
row={row}
column={{
dataKey: column.dataKey,
Expand All @@ -55,9 +55,19 @@ TableFooterRow.propTypes = {
compact: PropTypes.bool.isRequired,
};

const TableFoot = ({ columns, rows, keyField, loading, compact }) => (
<tfoot>{renderRows(rows, columns, keyField, loading, compact)}</tfoot>
);
const TableFoot = ({
columns,
rows,
keyField,
loading,
compact,
}: {
columns: Columns;
rows: RowType[];
keyField?: string;
loading?: boolean;
compact?: boolean;
}) => <tfoot>{renderRows(rows, columns, keyField, loading, compact)}</tfoot>;

TableFoot.propTypes = {
columns: columnsPropType.isRequired,
Expand Down
6 changes: 3 additions & 3 deletions src/Table/TableHead.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import React from "react";
import styled from "styled-components";
import StyledTh from "./StyledTh";
import { ColumnType } from "./Table.types";
import { Columns } from "./Table.types";

type TableHeadProps = {
columns: ColumnType[];
columns: Columns;
compact?: boolean;
sticky?: boolean;
};
Expand All @@ -23,7 +23,7 @@ const TableHead: React.FC<TableHeadProps> = ({ columns, compact, sticky }) => {
allColumns.map((column) => (
<StyledTh
scope="col"
key={column.dataKey}
key={column.dataKey ?? column.key ?? index}
width={column.width}
compact={compact}
data-testid="table-head"
Expand Down

0 comments on commit 6f3c100

Please sign in to comment.