mirror of
https://github.com/DOI-DO/j40-cejst-2.git
synced 2025-08-16 06:11:41 -07:00
Implement downloads page and May 25th timed copy changes (#1653)
* Add initial side nav * Add Download page as a sub-page under Meth&Data - udpate S3 file path in .envs - remove the DownloadPacket component - move download copy from methodology to download - modify header to use two types of navs: -- mobile (with sub-pages) and -- desktop (without subpages) - create a SubPageNav component - add SubPagNav to Meth and Download page - update snapshots - add global CSS overide to remove minus sign on mobile nav link accordion as it's permanently open * Remove the update tag above Public eng button * Make the 3rd bullet on explore page update on 5/25 * Make the RFI box text change after 5/25/22 * Update site with RFI expired copy, remove Alerts - add Spanish translations - update snapshots * Fix typo on XLS file path * Refactor HowYouCanHelp to standard form * Add custom download links with icons - add new DownloadLink compnent - add Spanish translations * Update download file sizes * Allow meth&data nav link to collapse on mobile
This commit is contained in:
parent
ef46af00f8
commit
226017654a
46 changed files with 966 additions and 1720 deletions
|
@ -0,0 +1,7 @@
|
|||
@use '../../styles/design-system.scss' as *;
|
||||
|
||||
.downloadIcon {
|
||||
height: 1rem;
|
||||
vertical-align: middle;
|
||||
filter: invert(57%) sepia(6%) saturate(3932%) hue-rotate(163deg) brightness(86%) contrast(88%);
|
||||
}
|
13
client/src/components/DownloadLink/DownloadLink.module.scss.d.ts
vendored
Normal file
13
client/src/components/DownloadLink/DownloadLink.module.scss.d.ts
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
declare namespace DownloadLinkNamespace {
|
||||
export interface IDownloadLink {
|
||||
downloadIcon: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare const DownloadLinkModule: DownloadLinkNamespace.IDownloadLink & {
|
||||
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
|
||||
locals: DownloadLinkNamespace.IDownloadLink;
|
||||
};
|
||||
|
||||
export = DownloadLinkModule;
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
import * as React from 'react';
|
||||
import {render} from '@testing-library/react';
|
||||
import {LocalizedComponent} from '../../test/testHelpers';
|
||||
import DownloadPacket from './DownloadPacket';
|
||||
import DownloadLink from './DownloadLink';
|
||||
|
||||
describe('download packet component defined', () => {
|
||||
describe('rendering of the DownloadLink disadvantaged', () => {
|
||||
const {asFragment} = render(
|
||||
<LocalizedComponent>
|
||||
<DownloadPacket />
|
||||
<DownloadLink href="https://google.com" linkText="Google"/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
|
||||
|
@ -14,4 +14,3 @@ describe('download packet component defined', () => {
|
|||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
40
client/src/components/DownloadLink/DownloadLink.tsx
Normal file
40
client/src/components/DownloadLink/DownloadLink.tsx
Normal file
|
@ -0,0 +1,40 @@
|
|||
import React from 'react';
|
||||
import {defineMessages, useIntl} from 'gatsby-plugin-intl';
|
||||
|
||||
import {IDefineMessage} from '../../data/copy/common';
|
||||
|
||||
// @ts-ignore
|
||||
import fileDownloadIcon from '/node_modules/uswds/dist/img/usa-icons/file_download.svg';
|
||||
import * as styles from './DownloadLink.module.scss';
|
||||
|
||||
export const DOWNLOAD_ICON = defineMessages({
|
||||
ALT_TAG: {
|
||||
id: 'downloads.page.download.icon.alt.tag',
|
||||
defaultMessage: 'The icon used to indicate that the file is downloadable',
|
||||
description: 'Navigate to the Downloads page, this is the icon used to indicate that the file is downloadable',
|
||||
},
|
||||
});
|
||||
|
||||
interface IDownloadLink {
|
||||
href: string | IDefineMessage,
|
||||
linkText: string | JSX.Element,
|
||||
}
|
||||
const DownloadLink = ({href, linkText}:IDownloadLink) => {
|
||||
const intl = useIntl();
|
||||
|
||||
if (href && typeof href !== `string`) {
|
||||
href = intl.formatMessage(href);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<a href={href} download>{linkText}</a>
|
||||
<img
|
||||
className={styles.downloadIcon}
|
||||
src={fileDownloadIcon}
|
||||
alt={intl.formatMessage(DOWNLOAD_ICON.ALT_TAG)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DownloadLink;
|
|
@ -0,0 +1,16 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`rendering of the DownloadLink disadvantaged checks if component renders 1`] = `
|
||||
<DocumentFragment>
|
||||
<a
|
||||
download=""
|
||||
href="https://google.com"
|
||||
>
|
||||
Google
|
||||
</a>
|
||||
<img
|
||||
alt="The icon used to indicate that the file is downloadable"
|
||||
src="test-file-stub"
|
||||
/>
|
||||
</DocumentFragment>
|
||||
`;
|
3
client/src/components/DownloadLink/index.tsx
Normal file
3
client/src/components/DownloadLink/index.tsx
Normal file
|
@ -0,0 +1,3 @@
|
|||
import DownloadLink from './DownloadLink';
|
||||
|
||||
export default DownloadLink;
|
|
@ -1,94 +0,0 @@
|
|||
import React, {FC} from 'react';
|
||||
import {Button, Grid, Tag} from '@trussworks/react-uswds';
|
||||
|
||||
import * as styles from './downloadPacket.module.scss';
|
||||
import * as METHODOLOGY_COPY from '../../data/copy/methodology';
|
||||
|
||||
// @ts-ignore
|
||||
import downloadIcon from '/node_modules/uswds/dist/img/usa-icons/file_download.svg';
|
||||
|
||||
const DownloadPacket = () => {
|
||||
// inline components to make build layout below more readable
|
||||
const UpdateTag = () => <div className={styles.tagContainer}><Tag
|
||||
className={styles.updateTag}>{METHODOLOGY_COPY.DOWNLOAD_PACKAGE.UPDATED_TAG}</Tag></div>;
|
||||
|
||||
const NewTag = () => <div className={styles.tagContainer}>
|
||||
<Tag className={styles.newTag}>{METHODOLOGY_COPY.DOWNLOAD_PACKAGE.NEW_TAG}</Tag></div>;
|
||||
|
||||
const DownloadButton: FC = ({children}) =>
|
||||
<Button className={styles.downloadBoxButton} type="button">
|
||||
<span className={styles.downloadButtonIconSpan}>
|
||||
<img src={downloadIcon} className={styles.downloadButtonIcon}
|
||||
alt={'download icon for download package'} />
|
||||
</span>
|
||||
<span className={styles.downloadButtonText} >
|
||||
{children}
|
||||
</span>
|
||||
</Button>;
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<div className={styles.downloadBoxContainer}>
|
||||
<div className={styles.downloadBox}>
|
||||
<div className={styles.downloadBoxTextBox}>
|
||||
|
||||
{/* Download box title */}
|
||||
<div className={styles.downloadBoxTitle}>
|
||||
{METHODOLOGY_COPY.DOWNLOAD_PACKAGE.TITLE}
|
||||
</div>
|
||||
|
||||
{/* Download box description 1 */}
|
||||
<div className={styles.downloadSourceText}>
|
||||
{METHODOLOGY_COPY.DOWNLOAD_PACKAGE.DESCRIPTION1}
|
||||
</div>
|
||||
|
||||
{/* Download box button 1 */}
|
||||
<div className={styles.downloadButtonContainer}>
|
||||
<UpdateTag/>
|
||||
<a data-cy={'download-link'}
|
||||
download
|
||||
href={METHODOLOGY_COPY.DOWNLOAD_ZIP_URL}>
|
||||
<DownloadButton>{METHODOLOGY_COPY.DOWNLOAD_PACKAGE.BUTTON_TEXT1}</DownloadButton>
|
||||
</a>
|
||||
</div>
|
||||
<div className={styles.lastUpdated}>
|
||||
{METHODOLOGY_COPY.DOWNLOAD_PACKAGE.ZIP_LAST_UPDATED}
|
||||
</div>
|
||||
|
||||
|
||||
{/* Download box button 2 */}
|
||||
<div className={styles.downloadButtonContainer}>
|
||||
<UpdateTag/>
|
||||
<a data-cy={'shapefile-link'}
|
||||
download
|
||||
href={METHODOLOGY_COPY.DOWNLOAD_SHAPEFILE_URL}>
|
||||
<DownloadButton>{METHODOLOGY_COPY.DOWNLOAD_PACKAGE.BUTTON_TEXT2}</DownloadButton>
|
||||
</a>
|
||||
</div>
|
||||
<div className={styles.lastUpdated}>
|
||||
{METHODOLOGY_COPY.DOWNLOAD_PACKAGE.SHAPE_LAST_UPDATED}
|
||||
</div>
|
||||
|
||||
{/* Download box button 3 */}
|
||||
<div className={styles.downloadButtonContainer}>
|
||||
<NewTag/>
|
||||
{/* target and rel required since PDFs open in browser and don't download */}
|
||||
<a data-cy={'tsd-link'}
|
||||
download
|
||||
target={'_blank'}
|
||||
rel={'noreferrer'}
|
||||
href={METHODOLOGY_COPY.DOWNLOAD_TSD_URL}>
|
||||
<DownloadButton>{METHODOLOGY_COPY.DOWNLOAD_PACKAGE.BUTTON_TEXT3}</DownloadButton>
|
||||
</a>
|
||||
</div>
|
||||
<div className={styles.lastUpdated}>
|
||||
{METHODOLOGY_COPY.DOWNLOAD_PACKAGE.TSD_LAST_UPDATED}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export default DownloadPacket;
|
|
@ -1,148 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`download packet component defined checks if component renders 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class=""
|
||||
data-testid="grid"
|
||||
>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<span>
|
||||
NEW
|
||||
</span>
|
||||
files available for download
|
||||
</div>
|
||||
<div>
|
||||
Download the data sources used in the CEJST (.csv, .xlxs,
|
||||
<span>
|
||||
.pdf
|
||||
</span>
|
||||
that describes how to use the list, and a
|
||||
<span>
|
||||
codebook
|
||||
</span>
|
||||
, 53MB unzipped), the shapefile, along with a
|
||||
<span>
|
||||
codebook
|
||||
</span>
|
||||
(.zip, 742MB unzipped) or the technical support document (.pdf, 2.5MB unzipped).
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<span
|
||||
class="usa-tag"
|
||||
data-testid="tag"
|
||||
>
|
||||
<strong>
|
||||
Updated
|
||||
</strong>
|
||||
</span>
|
||||
</div>
|
||||
<a
|
||||
data-cy="download-link"
|
||||
download=""
|
||||
href="//"
|
||||
>
|
||||
<button
|
||||
class="usa-button"
|
||||
data-testid="button"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
<img
|
||||
alt="download icon for download package"
|
||||
src="test-file-stub"
|
||||
/>
|
||||
</span>
|
||||
<span>
|
||||
Download data sources
|
||||
</span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
Last updated: 05/04/22
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<span
|
||||
class="usa-tag"
|
||||
data-testid="tag"
|
||||
>
|
||||
<strong>
|
||||
Updated
|
||||
</strong>
|
||||
</span>
|
||||
</div>
|
||||
<a
|
||||
data-cy="shapefile-link"
|
||||
download=""
|
||||
href="//"
|
||||
>
|
||||
<button
|
||||
class="usa-button"
|
||||
data-testid="button"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
<img
|
||||
alt="download icon for download package"
|
||||
src="test-file-stub"
|
||||
/>
|
||||
</span>
|
||||
<span>
|
||||
Download shapefile
|
||||
</span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
Last updated: 04/26/22
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<span
|
||||
class="usa-tag"
|
||||
data-testid="tag"
|
||||
>
|
||||
<strong>
|
||||
NEW
|
||||
</strong>
|
||||
</span>
|
||||
</div>
|
||||
<a
|
||||
data-cy="tsd-link"
|
||||
download=""
|
||||
href="//"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<button
|
||||
class="usa-button"
|
||||
data-testid="button"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
<img
|
||||
alt="download icon for download package"
|
||||
src="test-file-stub"
|
||||
/>
|
||||
</span>
|
||||
<span>
|
||||
Download technical support document
|
||||
</span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
Last updated: 04/19/22
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
|
@ -1,114 +0,0 @@
|
|||
@use '../../styles/design-system.scss' as *;
|
||||
|
||||
@mixin baseButtonContainerStyles {
|
||||
align-self: center;
|
||||
@include u-margin-top(2);
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
img {
|
||||
// This should be a global css-filter value as it's generated
|
||||
// from the primary color.
|
||||
filter: invert(15%) sepia(9%) saturate(5666%) hue-rotate(175deg) brightness(96%) contrast(95%);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin baseTextStyle {
|
||||
@include typeset('sans', 'xs', 3);
|
||||
@include u-margin-top(2);
|
||||
@include u-margin-bottom(2);
|
||||
|
||||
};
|
||||
|
||||
@mixin baseButtonTextStyle {
|
||||
padding-top: 4px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.downloadBoxContainer {
|
||||
color: whitesmoke;
|
||||
margin: auto;
|
||||
@include u-margin-top(2.5);
|
||||
|
||||
.downloadBox {
|
||||
@include u-bg('blue-80v');
|
||||
border-radius: 6px 6px;
|
||||
// @include u-margin-top(3);
|
||||
|
||||
.downloadBoxTextBox {
|
||||
padding: 25px 25px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.downloadBoxTitle {
|
||||
@include typeset('sans', 'xs', 3);
|
||||
@include u-text('semibold');
|
||||
}
|
||||
|
||||
.downloadSourceText {
|
||||
@include u-margin-top(2);
|
||||
}
|
||||
|
||||
// Last updated
|
||||
.lastUpdated {
|
||||
font-style: italic;
|
||||
align-self: center;
|
||||
@include u-margin-top(1);
|
||||
}
|
||||
|
||||
// Data source button (scoped)
|
||||
.downloadButtonContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@include baseButtonContainerStyles();
|
||||
text-align: center;
|
||||
|
||||
.downloadButtonText {
|
||||
@include baseButtonTextStyle();
|
||||
@include u-margin-right(1);
|
||||
}
|
||||
|
||||
.downloadButtonIconSpan {
|
||||
display: contents;
|
||||
max-width: 1.5em;
|
||||
}
|
||||
|
||||
.downloadButtonIcon {
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.downloadBoxButton {
|
||||
@include u-bg('white');
|
||||
@include u-color('blue-80v');
|
||||
display: flex;
|
||||
width: 16em;
|
||||
}
|
||||
|
||||
.tagContainer {
|
||||
align-self: end;
|
||||
@include u-margin-bottom(-1);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.newTag {
|
||||
@include u-text('bold');
|
||||
@include u-text("blue-80v");
|
||||
@include u-bg("gold-20v");
|
||||
}
|
||||
|
||||
.updateTag {
|
||||
@include u-text('bold');
|
||||
@include u-text("blue-80v");
|
||||
@include u-bg("gray-10");
|
||||
}
|
||||
|
||||
.newCalloutFontColor {
|
||||
@include u-text("gold-20v");
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
declare namespace DownloadPacketModuleScssNamespace {
|
||||
export interface IDownloadPacketModuleScss {
|
||||
downloadBoxContainer: string;
|
||||
downloadBox: string;
|
||||
downloadBoxTextBox: string;
|
||||
downloadBoxTitle: string;
|
||||
downloadSourceText: string;
|
||||
downloadButtonContainer: string;
|
||||
downloadBoxButton: string;
|
||||
downloadButtonText: string;
|
||||
downloadButtonIconSpan: string;
|
||||
downloadButtonIcon: string;
|
||||
tagContainer: string;
|
||||
newTag: string;
|
||||
updateTag: string;
|
||||
newCalloutFontColor: string;
|
||||
lastUpdated:string;
|
||||
}
|
||||
}
|
||||
|
||||
declare const DownloadPacketModuleScssModule: DownloadPacketModuleScssNamespace.IDownloadPacketModuleScss & {
|
||||
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
|
||||
locals: DownloadPacketModuleScssNamespace.IDownloadPacketModuleScss;
|
||||
};
|
||||
|
||||
export = DownloadPacketModuleScssModule;
|
|
@ -1,3 +0,0 @@
|
|||
import DownloadPacket from './DownloadPacket';
|
||||
|
||||
export default DownloadPacket;
|
27
client/src/components/HowYouCanHelp/HowYouCanHelp.tsx
Normal file
27
client/src/components/HowYouCanHelp/HowYouCanHelp.tsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
import React from 'react';
|
||||
|
||||
import * as styles from './howYouCanHelp.module.scss';
|
||||
import * as EXPLORE_COPY from '../../data/copy/explore';
|
||||
|
||||
const HowYouCanHelp = () => {
|
||||
return (
|
||||
<div className={styles.howYouCanHelpContainer}>
|
||||
<h2>
|
||||
{EXPLORE_COPY.HOW_YOU_CAN_HELP_LIST_ITEMS.HEADING}
|
||||
</h2>
|
||||
<ul className={styles.howYouCanHelpListWrapper}>
|
||||
<li className={styles.howYouCanHelpList}>
|
||||
{EXPLORE_COPY.HOW_YOU_CAN_HELP_LIST_ITEMS.LIST_ITEM_1}
|
||||
</li>
|
||||
<li className={styles.howYouCanHelpList}>
|
||||
{EXPLORE_COPY.HOW_YOU_CAN_HELP_LIST_ITEMS.LIST_ITEM_2}
|
||||
</li>
|
||||
<li className={styles.howYouCanHelpList}>
|
||||
{EXPLORE_COPY.HOW_YOU_CAN_HELP_LIST_ITEMS.LIST_ITEM_3}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default HowYouCanHelp;
|
|
@ -1,27 +1,3 @@
|
|||
import React from 'react';
|
||||
|
||||
import * as styles from './howYouCanHelp.module.scss';
|
||||
import * as EXPLORE_COPY from '../../data/copy/explore';
|
||||
|
||||
const HowYouCanHelp = () => {
|
||||
return (
|
||||
<div className={styles.howYouCanHelpContainer}>
|
||||
<h2>
|
||||
{EXPLORE_COPY.HOW_YOU_CAN_HELP_LIST_ITEMS.HEADING}
|
||||
</h2>
|
||||
<ul className={styles.howYouCanHelpListWrapper}>
|
||||
<li className={styles.howYouCanHelpList}>
|
||||
{EXPLORE_COPY.HOW_YOU_CAN_HELP_LIST_ITEMS.LIST_ITEM_1}
|
||||
</li>
|
||||
<li className={styles.howYouCanHelpList}>
|
||||
{EXPLORE_COPY.HOW_YOU_CAN_HELP_LIST_ITEMS.LIST_ITEM_2}
|
||||
</li>
|
||||
<li className={styles.howYouCanHelpList}>
|
||||
{EXPLORE_COPY.HOW_YOU_CAN_HELP_LIST_ITEMS.LIST_ITEM_3}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
import HowYouCanHelp from './HowYouCanHelp';
|
||||
|
||||
export default HowYouCanHelp;
|
||||
|
|
|
@ -30,17 +30,7 @@ exports[`rendering of the HowYouCanHelp checks if various text fields are visibl
|
|||
.
|
||||
</li>
|
||||
<li>
|
||||
Respond to our Request for Information on
|
||||
<a
|
||||
class="usa-link usa-link--external"
|
||||
data-cy=""
|
||||
href="https://www.federalregister.gov/d/2022-03920"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
federalregister.gov
|
||||
</a>
|
||||
.
|
||||
The Request for Information on the Federal Register is now closed.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -5,14 +5,14 @@ import {
|
|||
NavMenuButton,
|
||||
PrimaryNav,
|
||||
Grid,
|
||||
Alert,
|
||||
// NavDropDownButton,
|
||||
// Menu,
|
||||
NavDropDownButton,
|
||||
Menu,
|
||||
} from '@trussworks/react-uswds';
|
||||
import BetaBanner from '../BetaBanner';
|
||||
import J40MainGridContainer from '../J40MainGridContainer';
|
||||
import GovernmentBanner from '../GovernmentBanner';
|
||||
import Language from '../Language';
|
||||
import {useWindowSize} from 'react-use';
|
||||
|
||||
// @ts-ignore
|
||||
import siteLogo from '../../images/j40-logo-v2.png';
|
||||
|
@ -20,73 +20,79 @@ import * as styles from './J40Header.module.scss';
|
|||
import * as COMMON_COPY from '../../data/copy/common';
|
||||
import {PAGES_ENDPOINTS} from '../../data/constants';
|
||||
|
||||
/**
|
||||
* The J40Header component will control how the header looks for both mobile and desktop
|
||||
*
|
||||
* The Header is defined as
|
||||
* 1. Two rows of Banners (ie, official gov website and beta site)
|
||||
* 2. Logo and Nav Links Row
|
||||
* 3. Any Alerts
|
||||
*
|
||||
* @return {JSX.Element}
|
||||
*/
|
||||
const J40Header = () => {
|
||||
const intl = useIntl();
|
||||
const {width} = useWindowSize();
|
||||
|
||||
const titleL1 = intl.formatMessage(COMMON_COPY.HEADER.TITLE_LINE_1);
|
||||
const titleL2 = intl.formatMessage(COMMON_COPY.HEADER.TITLE_LINE_2);
|
||||
// Logo text
|
||||
const logoLine1 = intl.formatMessage(COMMON_COPY.HEADER.TITLE_LINE_1);
|
||||
const logoLine2 = intl.formatMessage(COMMON_COPY.HEADER.TITLE_LINE_2);
|
||||
|
||||
/**
|
||||
* State variable to control the mobile menu toggle
|
||||
* State variable to control the toggling of mobile menu button
|
||||
*/
|
||||
const [mobileNavOpen, setMobileNavOpen] = useState(false);
|
||||
const toggleMobileNav = (): void =>
|
||||
setMobileNavOpen((prevOpen) => !prevOpen);
|
||||
|
||||
/**
|
||||
* State variable to hold the open/close state of each nav dropdown. This will allow for two
|
||||
* dropdown that are being used, each corresponding to an index in the state array:
|
||||
*
|
||||
* index 0 = Data & Methodology dropdown (being used)
|
||||
* index 1 = About dropdown (removed for now)
|
||||
*/
|
||||
const [isOpen, setIsOpen] = useState([true]);
|
||||
const onToggle = (index: number): void => {
|
||||
setIsOpen((prevIsOpen) => {
|
||||
const newIsOpen = [true];
|
||||
newIsOpen[index] = !prevIsOpen[index];
|
||||
return newIsOpen;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* The original work of this release called for creating a download page, a FAQ page and TSD page. These
|
||||
* were to be embedded in dropdown menus in the navigation bar of the header. These were all completed.
|
||||
* After discovering that the dropdown component from USWDS was not operating as expected, we decided to
|
||||
* revert to another design.
|
||||
*
|
||||
* It was also decided that some more design was needed and that these pages along with their designs will
|
||||
* be used in the near future. Rather than deleted the code or moving it to another branch, the assumption
|
||||
* was made that since this will be added back in the near term, let's comment it out for now.
|
||||
*
|
||||
* If for some reason we haven't integrated this logic in the near future, this code will be deleted.
|
||||
* On mobile, the Methodology & Data page should have two sub-nav links. This defines
|
||||
* the array that will hold these links
|
||||
*/
|
||||
const methPageSubNavLinks = [
|
||||
<Link
|
||||
to={PAGES_ENDPOINTS.METHODOLOGY}
|
||||
key={'methodology'}
|
||||
activeClassName="usa-current"
|
||||
data-cy={'nav-link-methodology'}>
|
||||
{intl.formatMessage(COMMON_COPY.HEADER.METHODOLOGY)}
|
||||
</Link>,
|
||||
<Link
|
||||
to={PAGES_ENDPOINTS.DOWNLOADS}
|
||||
key={'downloads'}
|
||||
activeClassName="usa-current"
|
||||
data-cy={'nav-link-downloads'}>
|
||||
{intl.formatMessage(COMMON_COPY.HEADER.DOWNLOADS)}
|
||||
</Link>,
|
||||
// <Link
|
||||
// to={PAGES_ENDPOINTS.TSD}
|
||||
// key={'tsd'}
|
||||
// activeClassName="usa-current"
|
||||
// data-cy={'nav-link-technical-support-docs'}>
|
||||
// {intl.formatMessage(COMMON_COPY.HEADER.TSD)}
|
||||
// </Link>,
|
||||
];
|
||||
|
||||
/**
|
||||
* State variable to hold the open/close state of each nav dropdown. There are currently two
|
||||
* dropdowns that are being used, each corresponding to an index in the state array:
|
||||
*
|
||||
* index 0 = Data & Methodology dropdown
|
||||
* index 1 = About dropdown
|
||||
* In the future, we may want to add sub-pages to the About page. This array will
|
||||
* define the sub-pages for the About page.
|
||||
*/
|
||||
// const [isOpen, setIsOpen] = useState([false, false]);
|
||||
// const onToggle = (index: number): void => {
|
||||
// setIsOpen((prevIsOpen) => {
|
||||
// const newIsOpen = [false, false];
|
||||
// newIsOpen[index] = !prevIsOpen[index];
|
||||
// return newIsOpen;
|
||||
// });
|
||||
// };
|
||||
|
||||
// const methPageSubNavLinks = [
|
||||
// <Link
|
||||
// to={PAGES_ENDPOINTS.METHODOLOGY}
|
||||
// key={'methodology'}
|
||||
// activeClassName="usa-current"
|
||||
// data-cy={'nav-link-methodology'}>
|
||||
// {intl.formatMessage(COMMON_COPY.HEADER.METHODOLOGY)}
|
||||
// </Link>,
|
||||
// <Link
|
||||
// to={PAGES_ENDPOINTS.DOWNLOADS}
|
||||
// key={'downloads'}
|
||||
// activeClassName="usa-current"
|
||||
// data-cy={'nav-link-downloads'}>
|
||||
// {intl.formatMessage(COMMON_COPY.HEADER.DOWNLOADS)}
|
||||
// </Link>,
|
||||
// <Link
|
||||
// to={PAGES_ENDPOINTS.TSD}
|
||||
// key={'tsd'}
|
||||
// activeClassName="usa-current"
|
||||
// data-cy={'nav-link-technical-support-docs'}>
|
||||
// {intl.formatMessage(COMMON_COPY.HEADER.TSD)}
|
||||
// </Link>,
|
||||
// ];
|
||||
|
||||
// const aboutSubNavLinks = [
|
||||
// <Link
|
||||
// to={PAGES_ENDPOINTS.ABOUT}
|
||||
|
@ -111,6 +117,17 @@ const J40Header = () => {
|
|||
// </Link>,
|
||||
// ];
|
||||
|
||||
|
||||
/**
|
||||
* This is the array that holds the navigation links and eventually is the one
|
||||
* that is passed to the render function. It only defines Explore, About and
|
||||
* Contact.
|
||||
*
|
||||
* The Methodology & Data link is passed in depending on screen size.
|
||||
*
|
||||
* For mobile: the Methodology & Data link should have sub-pages
|
||||
* For desktop: the Methodology & Data link should NOT have sub-pages
|
||||
*/
|
||||
const navLinks = [
|
||||
<Link
|
||||
to={PAGES_ENDPOINTS.EXPLORE}
|
||||
|
@ -119,13 +136,6 @@ const J40Header = () => {
|
|||
data-cy={'nav-link-explore-the-map'}>
|
||||
{intl.formatMessage(COMMON_COPY.HEADER.EXPLORE)}
|
||||
</Link>,
|
||||
<Link
|
||||
to={PAGES_ENDPOINTS.METHODOLOGY}
|
||||
key={'methodology'}
|
||||
activeClassName="usa-current"
|
||||
data-cy={'nav-link-methodology'}>
|
||||
{intl.formatMessage(COMMON_COPY.HEADER.METHODOLOGY)}
|
||||
</Link>,
|
||||
<Link
|
||||
to={PAGES_ENDPOINTS.ABOUT}
|
||||
key={'about'}
|
||||
|
@ -133,43 +143,6 @@ const J40Header = () => {
|
|||
data-cy={'nav-link-about'}>
|
||||
{intl.formatMessage(COMMON_COPY.HEADER.ABOUT)}
|
||||
</Link>,
|
||||
// <>
|
||||
// <NavDropDownButton
|
||||
// key="methDropDown"
|
||||
// label={intl.formatMessage(COMMON_COPY.HEADER.METHODOLOGY)}
|
||||
// menuId="methMenu"
|
||||
// isOpen={isOpen[0]}
|
||||
// onToggle={(): void => onToggle(0)}
|
||||
// data-cy={'nav-dropdown-methodology'}
|
||||
// className={styles.navDropDownBtn}
|
||||
// >
|
||||
// </NavDropDownButton>
|
||||
// <Menu
|
||||
// id='methMenu'
|
||||
// type='subnav'
|
||||
// items={methPageSubNavLinks}
|
||||
// isOpen={isOpen[0]}
|
||||
// >
|
||||
// </Menu>
|
||||
// </>,
|
||||
// <>
|
||||
// <NavDropDownButton
|
||||
// key="aboutDropDown"
|
||||
// label={intl.formatMessage(COMMON_COPY.HEADER.ABOUT)}
|
||||
// menuId="aboutMenu"
|
||||
// isOpen={isOpen[1]}
|
||||
// onToggle={(): void => onToggle(1)}
|
||||
// data-cy={'nav-dropdown-about'}
|
||||
// >
|
||||
// </NavDropDownButton>
|
||||
// <Menu
|
||||
// id='aboutMenu'
|
||||
// type='subnav'
|
||||
// items={aboutSubNavLinks}
|
||||
// isOpen={isOpen[1]}
|
||||
// >
|
||||
// </Menu>
|
||||
// </>,
|
||||
<Link
|
||||
to={PAGES_ENDPOINTS.CONTACT}
|
||||
key={'contact'}
|
||||
|
@ -182,6 +155,40 @@ const J40Header = () => {
|
|||
</div>,
|
||||
];
|
||||
|
||||
// For mobile: the Methodology & Data link should have sub-pages
|
||||
const MethPageNavWithSubPages = () =>
|
||||
<>
|
||||
<NavDropDownButton
|
||||
key="methDropDown"
|
||||
label={intl.formatMessage(COMMON_COPY.HEADER.METHODOLOGY)}
|
||||
menuId="methMenu"
|
||||
isOpen={isOpen[0]}
|
||||
onToggle={(): void => onToggle(0)}
|
||||
data-cy={'nav-dropdown-methodology'}
|
||||
>
|
||||
</NavDropDownButton>
|
||||
<Menu
|
||||
id='methMenu'
|
||||
type='subnav'
|
||||
items={methPageSubNavLinks}
|
||||
isOpen={isOpen[0]}
|
||||
>
|
||||
</Menu>
|
||||
</>;
|
||||
|
||||
// For desktop: the Methodology & Data link should NOT have sub-pages
|
||||
const MethPageNav = () =>
|
||||
<Link
|
||||
to={PAGES_ENDPOINTS.METHODOLOGY}
|
||||
key={'methodology'}
|
||||
activeClassName="usa-current"
|
||||
data-cy={'nav-link-methodology'}>
|
||||
{intl.formatMessage(COMMON_COPY.HEADER.METHODOLOGY)}
|
||||
</Link>;
|
||||
|
||||
// Modify navLinks to choose the appropriate Methodology & Data nav link depending on screen size
|
||||
navLinks.splice(1, 0, width > 1024 ? <MethPageNav/> : <MethPageNavWithSubPages/>);
|
||||
|
||||
return (
|
||||
<Header basic={true} role={'banner'}>
|
||||
|
||||
|
@ -196,15 +203,15 @@ const J40Header = () => {
|
|||
|
||||
{/* Logo */}
|
||||
<Grid col={1}>
|
||||
<img className={styles.logo} src={siteLogo} alt={`${titleL1} ${titleL2}`} />
|
||||
<img className={styles.logo} src={siteLogo} alt={`${logoLine1} ${logoLine2}`} />
|
||||
</Grid>
|
||||
|
||||
{/* Logo Title */}
|
||||
<Grid col={6}>
|
||||
<div className={styles.logoTitle}>
|
||||
<div>{titleL1}</div>
|
||||
<div>{logoLine1}</div>
|
||||
<div className={styles.title2BetaPill}>
|
||||
<div> {titleL2} </div>
|
||||
<div> {logoLine2} </div>
|
||||
<div className={styles.betaPill}>BETA</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -230,7 +237,7 @@ const J40Header = () => {
|
|||
</J40MainGridContainer>
|
||||
|
||||
{/* Alert */}
|
||||
{<J40MainGridContainer>
|
||||
{/* {<J40MainGridContainer>
|
||||
<Alert
|
||||
className={styles.alert}
|
||||
type="info"
|
||||
|
@ -245,7 +252,7 @@ const J40Header = () => {
|
|||
{COMMON_COPY.ALERTS.ALERT_1_DESCRIPTION}
|
||||
</Alert>
|
||||
</J40MainGridContainer>
|
||||
}
|
||||
} */}
|
||||
</Header>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -247,12 +247,43 @@ exports[`rendering of the J40Header checks if component renders 1`] = `
|
|||
<li
|
||||
class="usa-nav__primary-item"
|
||||
>
|
||||
<a
|
||||
data-cy="nav-link-methodology"
|
||||
href="/en/methodology"
|
||||
<button
|
||||
aria-controls="methMenu"
|
||||
aria-expanded="true"
|
||||
class="usa-accordion__button usa-nav__link"
|
||||
data-cy="nav-dropdown-methodology"
|
||||
data-testid="navDropDownButton"
|
||||
type="button"
|
||||
>
|
||||
Methodology & data
|
||||
</a>
|
||||
<span>
|
||||
Methodology & data
|
||||
</span>
|
||||
</button>
|
||||
<ul
|
||||
class="usa-nav__submenu"
|
||||
id="methMenu"
|
||||
>
|
||||
<li
|
||||
class="usa-nav__submenu-item"
|
||||
>
|
||||
<a
|
||||
data-cy="nav-link-methodology"
|
||||
href="/en/methodology"
|
||||
>
|
||||
Methodology & data
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="usa-nav__submenu-item"
|
||||
>
|
||||
<a
|
||||
data-cy="nav-link-downloads"
|
||||
href="/en/downloads"
|
||||
>
|
||||
Downloads
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li
|
||||
class="usa-nav__primary-item"
|
||||
|
@ -301,79 +332,6 @@ exports[`rendering of the J40Header checks if component renders 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="grid-container-desktop-lg"
|
||||
data-testid="gridContainer"
|
||||
>
|
||||
<div
|
||||
class="usa-alert usa-alert--info"
|
||||
data-testid="alert"
|
||||
>
|
||||
<div
|
||||
class="usa-alert__body"
|
||||
>
|
||||
<h4
|
||||
class="usa-alert__heading"
|
||||
>
|
||||
Additional documentation now available
|
||||
</h4>
|
||||
<p
|
||||
class="usa-alert__text"
|
||||
>
|
||||
Download new
|
||||
<a
|
||||
class="usa-link usa-link--external"
|
||||
data-cy=""
|
||||
href="https://static-data-screeningtool.geoplatform.gov/data-pipeline/data/score/downloadable/cejst_technical_support_document.pdf"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
technical support
|
||||
</a>
|
||||
and other documentation and
|
||||
<a
|
||||
class="usa-link usa-link--external"
|
||||
data-cy=""
|
||||
href="mailto:Screeningtool-Support@omb.eop.gov"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
send feedback
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="usa-alert usa-alert--info"
|
||||
data-testid="alert"
|
||||
>
|
||||
<div
|
||||
class="usa-alert__body"
|
||||
>
|
||||
<h4
|
||||
class="usa-alert__heading"
|
||||
>
|
||||
Public comment period extended
|
||||
</h4>
|
||||
<p
|
||||
class="usa-alert__text"
|
||||
>
|
||||
The public comment period for
|
||||
<a
|
||||
class="usa-link usa-link--external"
|
||||
data-cy=""
|
||||
href="https://www.federalregister.gov/documents/2022/04/25/2022-08774/climate-and-economic-justice-screening-tool-beta-version"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
sending feedback
|
||||
</a>
|
||||
via the Request for Information has been extended to May 25, 2022.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
|
|
@ -4,7 +4,7 @@ import {Link as TrussLink} from '@trussworks/react-uswds';
|
|||
|
||||
import {IDefineMessage} from '../../data/copy/common';
|
||||
|
||||
interface ILinkTypeWrapper {
|
||||
export interface ILinkTypeWrapper {
|
||||
linkText?: string | JSX.Element;
|
||||
internal?: boolean;
|
||||
url: string | IDefineMessage;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
@include u-padding-top(2.5);
|
||||
@include u-margin-top(4);
|
||||
|
||||
.link, .link:visited {
|
||||
color:white;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import React from 'react';
|
||||
import {useIntl, Link} from 'gatsby-plugin-intl';
|
||||
import {Button, Tag} from '@trussworks/react-uswds';
|
||||
import {
|
||||
Button,
|
||||
// Tag
|
||||
} from '@trussworks/react-uswds';
|
||||
|
||||
import * as styles from './PublicEngageButton.module.scss';
|
||||
import * as PUBLIC_ENG_COPY from '../../data/copy/publicEngage';
|
||||
|
@ -13,11 +16,12 @@ const PublicEngageButton = () => {
|
|||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.tagContainer}>
|
||||
{/* Remove Updated Tag for now */}
|
||||
{/* <div className={styles.tagContainer}>
|
||||
<Tag className={styles.tag}>
|
||||
{intl.formatMessage(PUBLIC_ENG_COPY.PUBLIC_ENG_BUTTON.TAG_LABEL)}
|
||||
</Tag>
|
||||
</div>
|
||||
</div> */}
|
||||
<Link className={styles.link} to={'/public-engagement'}>
|
||||
<Button
|
||||
type="button"
|
||||
|
|
|
@ -3,14 +3,6 @@
|
|||
exports[`rendering of the PublicEngageButton checks if component renders 1`] = `
|
||||
<DocumentFragment>
|
||||
<div>
|
||||
<div>
|
||||
<span
|
||||
class="usa-tag"
|
||||
data-testid="tag"
|
||||
>
|
||||
UPDATED
|
||||
</span>
|
||||
</div>
|
||||
<a
|
||||
href="/en/public-engagement"
|
||||
>
|
||||
|
|
|
@ -4,7 +4,6 @@ import {useIntl} from 'gatsby-plugin-intl';
|
|||
|
||||
import * as CONTACT_COPY from '../../data/copy/contact';
|
||||
import * as styles from './RequestForInfo.module.scss';
|
||||
import * as COMMON_COPY from '../../data/copy/common';
|
||||
|
||||
const RequestForInfo = () => {
|
||||
const intl = useIntl();
|
||||
|
@ -12,7 +11,6 @@ const RequestForInfo = () => {
|
|||
return (
|
||||
<SummaryBox className={styles.rfiBox} heading={intl.formatMessage(CONTACT_COPY.RFI_BOX.TITLE)}>
|
||||
<p>{CONTACT_COPY.RFI_BOX_BODY}</p>
|
||||
<p>{COMMON_COPY.ALERTS.ALERT_1_DESCRIPTION}</p>
|
||||
</SummaryBox>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -18,30 +18,7 @@ exports[`rendering of the RequestForInfo checks if component renders 1`] = `
|
|||
class="usa-summary-box__text"
|
||||
>
|
||||
<p>
|
||||
During the beta period, comments may be submitted on the Climate and Economic Justice Screening Tool via CEQ’s Request for Information available on
|
||||
<a
|
||||
class="usa-link usa-link--external"
|
||||
data-cy=""
|
||||
href="https://www.federalregister.gov/d/2022-03920"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
federalregister.gov
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<p>
|
||||
The public comment period for
|
||||
<a
|
||||
class="usa-link usa-link--external"
|
||||
data-cy=""
|
||||
href="https://www.federalregister.gov/documents/2022/04/25/2022-08774/climate-and-economic-justice-screening-tool-beta-version"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
sending feedback
|
||||
</a>
|
||||
via the Request for Information has been extended to May 25, 2022.
|
||||
The Request for Information on the Federal Register for the public beta period closed on May 25, 2022
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
0
client/src/components/SubPageNav/SubPageNav.module.scss
Normal file
0
client/src/components/SubPageNav/SubPageNav.module.scss
Normal file
0
client/src/components/SubPageNav/SubPageNav.module.scss.d.ts
vendored
Normal file
0
client/src/components/SubPageNav/SubPageNav.module.scss.d.ts
vendored
Normal file
35
client/src/components/SubPageNav/SubPageNav.test.tsx
Normal file
35
client/src/components/SubPageNav/SubPageNav.test.tsx
Normal file
|
@ -0,0 +1,35 @@
|
|||
import * as React from 'react';
|
||||
import {render} from '@testing-library/react';
|
||||
import {LocalizedComponent} from '../../test/testHelpers';
|
||||
import SubPageNav from './SubPageNav';
|
||||
|
||||
describe('rendering of the SubPageNav', () => {
|
||||
const firstLinkActive = 1;
|
||||
const secondLinkIndex = 2;
|
||||
|
||||
it('checks if the first link is active', () => {
|
||||
const {container} = render(
|
||||
<LocalizedComponent>
|
||||
<SubPageNav activeSubPageIndex={firstLinkActive}/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
|
||||
const firstLink = container.querySelector(`.usa-sidenav li:nth-child(${firstLinkActive}) a`);
|
||||
const secondLink = container.querySelector(`.usa-sidenav li:nth-child(${secondLinkIndex}) a`);
|
||||
expect(firstLink?.className).toBe('usa-current');
|
||||
expect(secondLink?.className).not.toBe('usa-current');
|
||||
});
|
||||
|
||||
it('checks if the second link is active', () => {
|
||||
const {container} = render(
|
||||
<LocalizedComponent>
|
||||
<SubPageNav activeSubPageIndex={secondLinkIndex}/>
|
||||
</LocalizedComponent>,
|
||||
);
|
||||
|
||||
const firstLink = container.querySelector(`.usa-sidenav li:nth-child(${firstLinkActive}) a`);
|
||||
const secondLink = container.querySelector(`.usa-sidenav li:nth-child(${secondLinkIndex}) a`);
|
||||
expect(secondLink?.className).toBe('usa-current');
|
||||
expect(firstLink?.className).not.toBe('usa-current');
|
||||
});
|
||||
});
|
39
client/src/components/SubPageNav/SubPageNav.tsx
Normal file
39
client/src/components/SubPageNav/SubPageNav.tsx
Normal file
|
@ -0,0 +1,39 @@
|
|||
import React from 'react';
|
||||
import {SideNav} from '@trussworks/react-uswds';
|
||||
import {useIntl} from 'gatsby-plugin-intl';
|
||||
|
||||
import LinkTypeWrapper from '../LinkTypeWrapper';
|
||||
import {PAGES_ENDPOINTS} from '../../data/constants';
|
||||
import * as COMMON_COPY from '../../data/copy/common';
|
||||
|
||||
// This prop is used to set which sub-page navigation is active
|
||||
interface ISubPageNav {
|
||||
activeSubPageIndex?: number;
|
||||
}
|
||||
|
||||
const SubPageNav = ({activeSubPageIndex}:ISubPageNav) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const subPages = [
|
||||
<LinkTypeWrapper
|
||||
key={0}
|
||||
className={activeSubPageIndex === 1 ? 'usa-current' : ''}
|
||||
url={PAGES_ENDPOINTS.METHODOLOGY}
|
||||
internal={true}
|
||||
linkText={intl.formatMessage(COMMON_COPY.HEADER.METHODOLOGY)}
|
||||
/>,
|
||||
<LinkTypeWrapper
|
||||
key={1}
|
||||
className={activeSubPageIndex === 2 ? 'usa-current' : ''}
|
||||
url={PAGES_ENDPOINTS.DOWNLOADS}
|
||||
internal={true}
|
||||
linkText={intl.formatMessage(COMMON_COPY.HEADER.DOWNLOADS)}
|
||||
/>,
|
||||
];
|
||||
|
||||
return (
|
||||
<SideNav items={subPages}/>
|
||||
);
|
||||
};
|
||||
|
||||
export default SubPageNav;
|
3
client/src/components/SubPageNav/index.tsx
Normal file
3
client/src/components/SubPageNav/index.tsx
Normal file
|
@ -0,0 +1,3 @@
|
|||
import SubPageNav from './SubPageNav';
|
||||
|
||||
export default SubPageNav;
|
Loading…
Add table
Add a link
Reference in a new issue