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 = (
- <>
-
- {caption}
- {buildColumnHeaders(columns)}
- {buildRows(visibleRows, columns)}
-
- {isPaginated ? : null}
- >
- );
-
- if (isScrollableHorizontal) {
- return (
-
- {tableContent}
-
+ const tableContent = (
+ <>
+
+ {caption}
+ {buildColumnHeaders(columns)}
+ {buildRows(visibleRows, columns)}
+
+ {isPaginated ? : null}
+ >
);
+
+ if (isScrollableHorizontal) {
+ return (
+
+ {tableContent}
+
+ );
+ }
+
+ return tableContent;
}
+);
- return tableContent;
-};
+Table.displayName = 'Table';
export default Table;