Skip to content

Commit

Permalink
feat(table): Add Card Cell and hideColumns property (#368)
Browse files Browse the repository at this point in the history
  • Loading branch information
diogomateus authored Jul 24, 2024
1 parent 7598bd7 commit c81b0bc
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 50 deletions.
18 changes: 17 additions & 1 deletion src/lib/components/table/Table.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ const initialData: TableData = [
{ rating: { type: 'zap', value: 3 } },
{ rating: { type: 'star', value: 3 } },
],
[
{
type: 'CARD',
colSpan: 3,
title: 'Dental add-on',
href: 'https://example.com',
description: 'Get your dental cleanings and additional treatments covered for just 10.90€ a month.',
},
],
],
},
{
Expand Down Expand Up @@ -163,7 +172,7 @@ const story = {
title: 'JSX/Table',
component: Table,
argTypes: {
data: {
tableData: {
subContent:
'This property allows to set the data of the Table component.',
},
Expand All @@ -189,6 +198,10 @@ const story = {
subContent:
'This property allows to set custom text for the show and hide details buttons.',
},
hideColumns: {
subContent:
'This property allows to hide defined columns by index.',
},
onSelectionChanged: {
subContent:
'This event is triggered when a selection is changed. It receives the index of the selection as an argument.',
Expand All @@ -215,12 +228,14 @@ const story = {
showDetails: 'Show details',
hideDetails: 'Hide details',
},
hideColumns: [],
},
};

export const TableStory = ({
collapsibleSections,
tableData,
hideColumns,
hideDetails,
stickyHeaderTopOffset,
textOverrides,
Expand Down Expand Up @@ -258,6 +273,7 @@ export const TableStory = ({
}}
collapsibleSections={collapsibleSections}
tableData={tableData}
hideColumns={hideColumns}
hideDetails={hideDetails}
stickyHeaderTopOffset={stickyHeaderTopOffset}
textOverrides={textOverrides}
Expand Down
9 changes: 7 additions & 2 deletions src/lib/components/table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface TableProps {
className?: string;
collapsibleSections?: boolean;
tableData: TableData;
hideColumns?: number[];
hideDetails?: boolean;
onModalOpen?: ModalFunction;
onSelectionChanged?: (index: number) => void;
Expand All @@ -49,6 +50,7 @@ const Table = ({
cellReplacements,
collapsibleSections,
tableData,
hideColumns = [],
hideDetails,
onModalOpen,
onSelectionChanged,
Expand Down Expand Up @@ -119,10 +121,12 @@ const Table = ({
>
<div className={styles.container} ref={headerRef}>
<TableSection
tableCellRows={[tableData?.[0]?.rows?.[0]]}
title={title}
cellReplacements={cellReplacements}
className={className}
hideColumns={hideColumns}
openModal={handleOpenModal}
tableCellRows={[tableData?.[0]?.rows?.[0]]}
title={title}
/>
</div>
</div>
Expand All @@ -134,6 +138,7 @@ const Table = ({
title={title}
className={className}
collapsibleSections={collapsibleSections}
hideColumns={hideColumns}
hideDetails={hideDetails}
isMobile={isMobile}
shouldHideDetails={shouldHideDetails}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.narrow {
height: 40px;
padding: 8px!important;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { DentalPlusIcon, PlaneIcon } from '../../../../icon';
import { CardCell } from './CardCell';

const story = {
title: 'JSX/Table/Cells',
component: CardCell,
argTypes: {},
args: {
title: 'Dental add-on',
description: 'Get your dental cleanings and additional treatments covered for just 10.90€ a month.',
icon: <DentalPlusIcon size={24} noMargin />,
href: 'https://example.com',
},
};

export const CardCellStory = ({
title,
description,
icon,
href,
}: React.ComponentProps<typeof CardCell>) => (
<div className="p48 d-flex fd-column gap16 bg-white">
<CardCell
title={title}
description={description}
icon={icon}
href={href}
/>
</div>
);

CardCellStory.storyName = 'CardCell';

export default story;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ReactNode } from 'react';
import { Card } from '../../../../cards/card';

export type CardCellProps = {
title: ReactNode;
description?: ReactNode;
icon?: ReactNode;
onClick?: () => void;
href: string;
cellId?: string;
};
export const CardCell = ({
title,
description,
icon,
onClick,
href,
}: CardCellProps) => {
return (
<div className="ta-left">
<Card
title={title}
description={description}
density='balanced'
icon={icon}
onClick={onClick}
{...(href && { href, as: 'a' })}
actionIcon={null}
showActionIcon={false}
/>
</div>
);
};
7 changes: 6 additions & 1 deletion src/lib/components/table/components/TableCell/TableCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import styles from './TableCell.module.scss';
import { BaseCell } from './BaseCell/BaseCell';
import { TableCellData } from '../../types';
import { CTACell } from './CTACell/CTACell';
import { CardCell } from './CardCell/CardCell';
import { ButtonCell } from './ButtonCell/ButtonCell';
import React from 'react';

Expand All @@ -12,6 +13,7 @@ type ExtraTableCellProps = {
isFirstCellInRow?: boolean;
isTopLeftCell?: boolean;
isNavigation?: boolean;
colSpan?: number;
};

export type TableCellProps = TableCellData & ExtraTableCellProps;
Expand All @@ -22,6 +24,7 @@ const TableCell = React.memo(
isHeader = false,
isNavigation = false,
isTopLeftCell = false,
colSpan = 0,
...cellProps
}: TableCellProps) => {
// prettier-ignore
Expand All @@ -43,9 +46,10 @@ const TableCell = React.memo(
{...scope}
className={classNames('bg-white py24 px8', styles.th, {
'ta-left': isFirstCellInRow,
[styles.fixedCell]: isFirstCellInRow,
[styles.fixedCell]: isFirstCellInRow && colSpan < 1,
pl32: isFirstCellInRow,
})}
colSpan={colSpan}
>
{!cellProps.type && (
<BaseCell
Expand All @@ -59,6 +63,7 @@ const TableCell = React.memo(
)}
{cellProps.type === 'CTA' && <CTACell {...cellProps} />}
{cellProps.type === 'BUTTON' && <ButtonCell {...cellProps} />}
{cellProps.type === 'CARD' && <CardCell {...cellProps} />}
</Tag>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface TableContentsProps {
className?: string;
collapsibleSections?: boolean;
tableData: TableData;
hideColumns: number[];
hideDetails?: boolean;
isMobile?: boolean;
openModal?: ModalFunction;
Expand All @@ -24,6 +25,7 @@ const TableContents = ({
className,
collapsibleSections,
tableData,
hideColumns = [],
hideDetails,
isMobile,
openModal,
Expand Down Expand Up @@ -89,6 +91,7 @@ const TableContents = ({
tableCellRows={
isFirstSection ? rows : [firstHeadRow, ...rows]
}
hideColumns={hideColumns}
hideHeader
openModal={openModal}
title={`${title}${
Expand Down
90 changes: 48 additions & 42 deletions src/lib/components/table/components/TableSection/TableSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import {
TableCellData,
TableCellRowData,
} from '../../types';
import { useCallback } from 'react';

export interface TableSectionProps {
className?: string;
tableCellRows: TableCellRowData[];
hideColumns: number[];
hideHeader?: boolean;
openModal?: ModalFunction;
title: string;
Expand All @@ -23,6 +25,7 @@ export interface TableSectionProps {
const TableSection = ({
className,
tableCellRows,
hideColumns = [],
hideHeader,
openModal,
title,
Expand Down Expand Up @@ -58,6 +61,12 @@ const TableSection = ({
return titleFromRow;
};

const isVisibleColumn = useCallback(
(cellIndex: number) => (
!hideColumns.includes(cellIndex)
), [hideColumns]
);

return (
<table
className={classNames(className, 'w100', styles.table)}
Expand Down Expand Up @@ -87,7 +96,7 @@ const TableSection = ({
},
} as TableCellData;

return (
return isVisibleColumn(cellIndex) && (
<TableCell
key={cellIndex}
isHeader
Expand All @@ -103,47 +112,44 @@ const TableSection = ({

<tbody>
{tableCellRows.map((row, rowIndex) => {
const isSingleCell = row.length === 1;

return (
rowIndex > 0 && (
<tr key={rowIndex} className={styles.tr}>
{row.map((tableCellData, cellIndex) => {
const key = `${rowIndex}-${cellIndex}`;
const isFirstCellInRow = cellIndex === 0;

const titleFromRow = getModalTitleFromRowHeader(row);
const titleFromColumnOrRow =
getModalTitleFromColumnHeader(cellIndex) ||
getModalTitleFromRowHeader(row);

const cellReplacementData =
(tableCellData.cellId &&
cellReplacements?.[tableCellData.cellId]) ||
{};

const cellProps = {
...tableCellData,
...cellReplacementData,
...{
openModal,
modalTitle: isFirstCellInRow
? titleFromRow
: titleFromColumnOrRow,
align: isFirstCellInRow ? 'left' : 'center',
},
} as TableCellData;

return (
<TableCell
isFirstCellInRow={isFirstCellInRow}
key={key}
{...cellProps}
/>
);
})}
</tr>
)

return rowIndex > 0 && (
<tr key={rowIndex} className={styles.tr}>
{row.map((tableCellData, cellIndex) => {
const key = `${rowIndex}-${cellIndex}`;
const isFirstCellInRow = cellIndex === 0;

const titleFromRow = getModalTitleFromRowHeader(row);
const titleFromColumnOrRow =
getModalTitleFromColumnHeader(cellIndex) ||
getModalTitleFromRowHeader(row);

const cellReplacementData =
(tableCellData.cellId &&
cellReplacements?.[tableCellData.cellId]) ||
{};

const cellProps = {
...tableCellData,
...cellReplacementData,
...{
openModal,
modalTitle: isFirstCellInRow
? titleFromRow
: titleFromColumnOrRow,
align: isFirstCellInRow ? 'left' : 'center',
},
} as TableCellData;

return !hideColumns.includes(cellIndex) && (
<TableCell
isFirstCellInRow={isFirstCellInRow}
key={key}
{...cellProps}
/>
);
})}
</tr>
);
})}
</tbody>
Expand Down
12 changes: 8 additions & 4 deletions src/lib/components/table/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ import { ReactNode } from 'react';
import { BaseCellProps } from './components/TableCell/BaseCell/BaseCell';
import { CTACellProps } from './components/TableCell/CTACell/CTACell';
import { ButtonCellProps } from './components/TableCell/ButtonCell/ButtonCell';
import { CardCellProps } from './components/TableCell/CardCell/CardCell';

type BaseCellData = BaseCellProps & { type?: undefined };
type CTACellData = CTACellProps & { type: 'CTA' };
type ButtonCellData = ButtonCellProps & { type: 'BUTTON' };
type DefaultCellProps = { colSpan?: number };

export type TableCellData = BaseCellData | CTACellData | ButtonCellData;
type BaseCellData = BaseCellProps & { type?: undefined } & DefaultCellProps;
type CTACellData = CTACellProps & { type: 'CTA' } & DefaultCellProps;
type ButtonCellData = ButtonCellProps & { type: 'BUTTON' } & DefaultCellProps;
type CardCellData = CardCellProps & { type: 'CARD' } & DefaultCellProps;

export type TableCellData = BaseCellData | CTACellData | ButtonCellData | CardCellData;

export const isBaseCell = (
tableCellData: TableCellData
Expand Down

0 comments on commit c81b0bc

Please sign in to comment.