diff --git a/src/components/PageHeader/PageHeader.test.tsx b/src/components/PageHeader/PageHeader.test.tsx index bc1af5c0..46847246 100644 --- a/src/components/PageHeader/PageHeader.test.tsx +++ b/src/components/PageHeader/PageHeader.test.tsx @@ -18,4 +18,14 @@ describe('PageHeader', () => { 'https://www.consumerfinance.gov' ); }); + + it('Renders with bottom border by default', () => { + const { container } = render(); + expect(container.firstChild.className).toBe('o-header bottom-border'); + }); + + it('Can be rendered without bottom border', () => { + const { container } = render(); + expect(container.firstChild.className).toBe('o-header'); + }); }); diff --git a/src/components/PageHeader/PageHeader.tsx b/src/components/PageHeader/PageHeader.tsx index 0f7e763e..7c6e5623 100644 --- a/src/components/PageHeader/PageHeader.tsx +++ b/src/components/PageHeader/PageHeader.tsx @@ -1,3 +1,4 @@ +import classnames from 'classnames'; import { Banner } from '../Banner/Banner'; import type { User } from '../Navbar/Navbar'; import Navbar from '../Navbar/Navbar'; @@ -7,15 +8,20 @@ interface PageHeaderProperties { links?: JSX.Element[]; user?: User; href?: string; + withBottomBorder?: boolean; } export default function PageHeader({ links, user, - href + href, + withBottomBorder = true }: PageHeaderProperties): JSX.Element { + const headerClasses = ['o-header']; + if (withBottomBorder) headerClasses.push('bottom-border'); + return ( -
+
diff --git a/src/components/PageHeader/header.less b/src/components/PageHeader/header.less index 7c4c2d28..4383e9e1 100644 --- a/src/components/PageHeader/header.less +++ b/src/components/PageHeader/header.less @@ -1,10 +1,14 @@ .o-header { min-width: 320px; - border-bottom: 5px solid #20aa3f; position: relative; z-index: 10; background-color: #ffffff; + + &.bottom-border { + border-bottom: 5px solid #20aa3f; + } } + @media only all and (min-width: 63.8125em) { .o-header { min-width: 1021px; diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx index bfc8516c..4b821e7a 100644 --- a/src/components/Table/Table.tsx +++ b/src/components/Table/Table.tsx @@ -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'; @@ -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): JSXElement => { if (!children) return null; return {children}; }; @@ -47,6 +50,9 @@ export interface TableProperties { perPage?: number; // Additional CSS classes className?: string; + // Refs for div and table elements + divRef?: ForwardedRef; + tableRef?: ForwardedRef; } /** @@ -54,63 +60,77 @@ export interface TableProperties { * * 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 & TableProperties): React.ReactElement => { - const [visibleRows, paginationProperties] = usePagination({ - rows, - isPaginated, - startPage, - perPage - }); +export const Table = forwardRef< + HTMLDivElement, + React.HTMLProps & 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 = ( - <> - - - {buildColumnHeaders(columns)} - {buildRows(visibleRows, columns)} -
{caption}
- {isPaginated ? : null} - - ); - - if (isScrollableHorizontal) { - return ( -
- {tableContent} -
+ const tableContent = ( + <> + + + {buildColumnHeaders(columns)} + {buildRows(visibleRows, columns)} +
{caption}
+ {isPaginated ? : null} + ); + + if (isScrollableHorizontal) { + return ( +
+ {tableContent} +
+ ); + } + + return tableContent; } +); - return tableContent; -}; +Table.displayName = 'Table'; export default Table;