Skip to content

Commit

Permalink
chore(Table): enabled ref forwarding (#358)
Browse files Browse the repository at this point in the history
closes #359

## Changes
- Adds ref forwarding
- adds a `divRef` and a `tableRef`

## How to test
- yarn test Table`

Reference
cfpb/sbl-frontend#547
  • Loading branch information
shindigira authored May 28, 2024
1 parent ddaa08e commit c040212
Showing 1 changed file with 74 additions and 54 deletions.
128 changes: 74 additions & 54 deletions src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import classNames from 'classnames';
import { type ReactNode } from 'react';
import type { ForwardedRef, HTMLProps } from 'react';
import { forwardRef, type ReactNode } from 'react';
import type { JSXElement } from '~/src/types/jsxElement';
import { type WidthPercent } from '../../types/WidthPercent';
import { Pagination } from '../Pagination/Pagination';
Expand All @@ -8,7 +9,9 @@ import { usePagination } from '../Pagination/usePagination';
import './table.less';
import { buildColumnHeaders, buildRows } from './tableUtils';

const Caption = ({ children }: { children: ReactNode }): JSXElement => {
const Caption = ({
children
}: HTMLProps<HTMLTableCaptionElement>): JSXElement => {
if (!children) return null;
return <caption>{children}</caption>;
};
Expand Down Expand Up @@ -47,70 +50,87 @@ export interface TableProperties {
perPage?: number;
// Additional CSS classes
className?: string;
// Refs for div and table elements
divRef?: ForwardedRef<HTMLDivElement>;
tableRef?: ForwardedRef<HTMLTableElement>;
}

/**
* Tables allow for the presentation of many data points grouped together in a visual way. They serve a unique purpose of allowing easy organization or comparison of more complex data than a chart or graph. They can be read either vertically (by columns) or horizontally (by rows).
*
* Source: https://cfpb.github.io/design-system/components/tables
*/
export const Table = ({
caption,
columns,
rows,
isResponsive = false,
isDirectory = false,
isScrollableHorizontal = false,
isStriped = false,
isPaginated = false,
startPage = MIN_PAGE,
perPage = DEFAULT_PER_PAGE,
className,
...others
}: React.HTMLProps<HTMLTableElement> & TableProperties): React.ReactElement => {
const [visibleRows, paginationProperties] = usePagination({
rows,
isPaginated,
startPage,
perPage
});
export const Table = forwardRef<
HTMLDivElement,
React.HTMLProps<HTMLTableElement> & TableProperties
>(
(
{
caption,
columns,
rows,
isResponsive = false,
isDirectory = false,
isScrollableHorizontal = false,
isStriped = false,
isPaginated = false,
startPage = MIN_PAGE,
perPage = DEFAULT_PER_PAGE,
className,
divRef,
tableRef,
...others
},
reference
): React.ReactElement => {
const [visibleRows, paginationProperties] = usePagination({
rows,
isPaginated,
startPage,
perPage
});

const tableClassnames = [];
const tableClassnames = [];

if (isResponsive || isDirectory)
tableClassnames.push('o-table o-table__stack-on-small');
if (isDirectory) tableClassnames.push('o-table__entry-header-on-small');
if (isStriped) tableClassnames.push('o-table__striped');
if (isPaginated) tableClassnames.push('u-w100pct');
if (className) tableClassnames.push(className);
if (isResponsive || isDirectory)
tableClassnames.push('o-table o-table__stack-on-small');
if (isDirectory) tableClassnames.push('o-table__entry-header-on-small');
if (isStriped) tableClassnames.push('o-table__striped');
if (isPaginated) tableClassnames.push('u-w100pct');
if (className) tableClassnames.push(className);

const tableContent = (
<>
<table
data-testid='table-testid'
className={classNames(tableClassnames)}
{...others}
>
<Caption>{caption}</Caption>
{buildColumnHeaders(columns)}
{buildRows(visibleRows, columns)}
</table>
{isPaginated ? <Pagination {...paginationProperties} /> : null}
</>
);

if (isScrollableHorizontal) {
return (
<div
data-testid='table-simple-scrollable'
className='o-table o-table-wrapper__scrolling'
>
{tableContent}
</div>
const tableContent = (
<>
<table
data-testid='table-testid'
className={classNames(tableClassnames)}
ref={tableRef}
{...others}
>
<Caption>{caption}</Caption>
{buildColumnHeaders(columns)}
{buildRows(visibleRows, columns)}
</table>
{isPaginated ? <Pagination {...paginationProperties} /> : null}
</>
);

if (isScrollableHorizontal) {
return (
<div
data-testid='table-simple-scrollable'
className='o-table o-table-wrapper__scrolling'
ref={reference ?? divRef}
>
{tableContent}
</div>
);
}

return tableContent;
}
);

return tableContent;
};
Table.displayName = 'Table';

export default Table;

0 comments on commit c040212

Please sign in to comment.