-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: New Component SiteAlert (#1099)
- Loading branch information
1 parent
492e8fe
commit 0e6e52c
Showing
4 changed files
with
323 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
/* eslint-disable jsx-a11y/anchor-is-valid */ | ||
|
||
import React from 'react' | ||
|
||
import { SiteAlert } from './SiteAlert' | ||
import { Link } from '../Link/Link' | ||
|
||
export default { | ||
title: 'Components/SiteAlert', | ||
component: SiteAlert, | ||
parameters: { | ||
docs: { | ||
description: { | ||
component: ` | ||
### USWDS 2.0 SiteAlert component | ||
Source: http://designsystem.digital.gov/components/site-alert | ||
`, | ||
}, | ||
}, | ||
}, | ||
argTypes: { | ||
slim: { | ||
control: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
showIcon: { | ||
control: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
variant: { | ||
control: { | ||
type: 'select', | ||
options: ['info', 'emergency'], | ||
}, | ||
defaultValue: 'info', | ||
}, | ||
}, | ||
} | ||
|
||
const infoHeading = 'Short alert message' | ||
|
||
const additionalContext = ( | ||
<p className="usa-alert__text"> | ||
Additional context and followup information including{' '} | ||
<Link className="usa-link" href="#"> | ||
a link | ||
</Link> | ||
. | ||
</p> | ||
) | ||
|
||
const emergencyHeading = 'Emergency alert message' | ||
|
||
const infoWithList = ( | ||
<ul className="usa-list"> | ||
<li> | ||
The primary informational message and{` `} | ||
<Link href="#">a link</Link> | ||
{` `}for supporting context. | ||
</li> | ||
<li> | ||
Another message,{` `} | ||
<Link href="#">and another link</Link>. | ||
</li> | ||
<li>A final informational message.</li> | ||
</ul> | ||
) | ||
|
||
const emergencyWithList = ( | ||
<ul className="usa-list"> | ||
<li> | ||
The primary emergency message and{` `} | ||
<Link href="#">a link</Link> | ||
{` `}for supporting context. | ||
</li> | ||
<li> | ||
Another message,{` `} | ||
<Link href="#">and another link</Link>. | ||
</li> | ||
<li>A final emergency message.</li> | ||
</ul> | ||
) | ||
|
||
const shortAlertContent = ( | ||
<p className="usa-alert__text"> | ||
<strong>Short alert message.</strong> | ||
Additional context and followup information including | ||
<Link href="#">a link</Link>. | ||
</p> | ||
) | ||
|
||
export const standardInformationalSiteAlert = (): React.ReactElement => ( | ||
<SiteAlert variant="info" heading={infoHeading}> | ||
{additionalContext} | ||
</SiteAlert> | ||
) | ||
|
||
export const standardEmergencySiteAlert = (): React.ReactElement => ( | ||
<SiteAlert variant="emergency" heading={emergencyHeading}> | ||
{additionalContext} | ||
</SiteAlert> | ||
) | ||
|
||
export const informationalAlertWithNoHeader = (): React.ReactElement => ( | ||
<SiteAlert variant="info">{shortAlertContent}</SiteAlert> | ||
) | ||
|
||
export const emergencyAlertWithNoHeader = (): React.ReactElement => ( | ||
<SiteAlert variant="emergency">{shortAlertContent}</SiteAlert> | ||
) | ||
|
||
export const informationalAlertWithList = (): React.ReactElement => ( | ||
<SiteAlert variant="info" heading={infoHeading}> | ||
{infoWithList} | ||
</SiteAlert> | ||
) | ||
|
||
export const emergencyAlertWithList = (): React.ReactElement => ( | ||
<SiteAlert | ||
variant="emergency" | ||
heading={emergencyHeading} | ||
aria-label="Site alert"> | ||
{emergencyWithList} | ||
</SiteAlert> | ||
) | ||
|
||
export const slimEmergencyAlert = (): React.ReactElement => ( | ||
<SiteAlert slim variant="emergency"> | ||
{shortAlertContent} | ||
</SiteAlert> | ||
) | ||
|
||
export const emergencyAlertNoIcon = (): React.ReactElement => ( | ||
<SiteAlert showIcon={false} variant="emergency"> | ||
{shortAlertContent} | ||
</SiteAlert> | ||
) | ||
|
||
export const alertWithCustomControls = (argTypes): React.ReactElement => ( | ||
<SiteAlert | ||
slim={argTypes.slim} | ||
showIcon={argTypes.showIcon} | ||
variant={argTypes.variant}> | ||
{shortAlertContent} | ||
</SiteAlert> | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/* eslint-disable jsx-a11y/anchor-is-valid, react/jsx-key */ | ||
import React from 'react' | ||
import { render } from '@testing-library/react' | ||
|
||
import { Link } from '../Link/Link' | ||
|
||
import { SiteAlert } from './SiteAlert' | ||
|
||
const testChildren = ( | ||
<p className="usa-alert__text"> | ||
some default text | ||
<Link href="#">with a link</Link>. | ||
</p> | ||
) | ||
|
||
const testDefaultProps = { | ||
heading: 'test heading', | ||
children: testChildren, | ||
} | ||
|
||
const testChildrenWithList = ( | ||
<ul> | ||
<li> | ||
some default text | ||
<Link href="#">with a link </Link> | ||
</li> | ||
<li> | ||
another list item | ||
<Link href="#">with a link</Link> | ||
</li> | ||
<li>another list item, no link</li> | ||
</ul> | ||
) | ||
|
||
describe('SiteAlert component', () => { | ||
it('renders without errors', () => { | ||
const { getByTestId, getByRole } = render( | ||
<SiteAlert variant="info" {...testDefaultProps} /> | ||
) | ||
|
||
expect(getByTestId('siteAlert')).toBeInTheDocument() | ||
expect(getByRole('link')).toBeInTheDocument() | ||
}) | ||
|
||
it('accepts a className', () => { | ||
const { getByTestId } = render( | ||
<SiteAlert | ||
variant="info" | ||
className="custom-class-name" | ||
{...testDefaultProps} | ||
/> | ||
) | ||
|
||
expect(getByTestId('siteAlert')).toHaveClass( | ||
'usa-site-alert usa-site-alert--info custom-class-name' | ||
) | ||
}) | ||
|
||
it('accepts a custom aria-label', () => { | ||
const { getByTestId } = render( | ||
<SiteAlert | ||
variant="emergency" | ||
aria-label="custom aria label" | ||
{...testDefaultProps} | ||
/> | ||
) | ||
|
||
expect(getByTestId('siteAlert')).toHaveAttribute( | ||
'aria-label', | ||
'custom aria label' | ||
) | ||
}) | ||
|
||
it('renders a passed in heading', () => { | ||
const { getByRole, queryByText } = render( | ||
<SiteAlert variant="info" {...testDefaultProps} /> | ||
) | ||
|
||
const heading = getByRole('heading') | ||
expect(heading).toBeInTheDocument() | ||
expect(heading).toHaveClass('usa-alert__heading') | ||
expect(queryByText('test heading')).toBeInTheDocument() | ||
}) | ||
|
||
it('renders emergency site alert without errors', () => { | ||
const { getByTestId } = render( | ||
<SiteAlert variant="emergency" {...testDefaultProps} /> | ||
) | ||
|
||
expect(getByTestId('siteAlert')).toHaveClass( | ||
'usa-site-alert usa-site-alert--emergency' | ||
) | ||
}) | ||
|
||
it('renders passed in link', () => { | ||
const { getByRole } = render( | ||
<SiteAlert variant="info">{testChildren}</SiteAlert> | ||
) | ||
|
||
expect(getByRole('link')).toBeInTheDocument() | ||
expect(getByRole('link')).toHaveClass('usa-link') | ||
}) | ||
|
||
it('renders a passed in list', () => { | ||
const { getAllByRole } = render( | ||
<SiteAlert variant="emergency">{testChildrenWithList}</SiteAlert> | ||
) | ||
expect(getAllByRole('link')).toHaveLength(2) | ||
}) | ||
|
||
it('renders slim and no icon when passed both, and does not apply no-header class', () => { | ||
const { getByTestId } = render( | ||
<SiteAlert variant="info" slim={true} showIcon={false}> | ||
{testChildren} | ||
</SiteAlert> | ||
) | ||
expect(getByTestId('siteAlert')).toHaveClass( | ||
'usa-site-alert usa-site-alert--info usa-site-alert--no-icon usa-site-alert--slim' | ||
) | ||
expect(getByTestId('siteAlert')).not.toHaveClass( | ||
'usa-site-alert--no-heading' | ||
) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import React from 'react' | ||
import classnames from 'classnames' | ||
|
||
interface SiteAlertProps { | ||
variant: 'info' | 'emergency' | ||
children: React.ReactNode | ||
heading?: string | ||
showIcon?: boolean | ||
slim?: boolean | ||
className?: string | ||
} | ||
|
||
export const SiteAlert = ({ | ||
variant, | ||
children, | ||
heading, | ||
showIcon = true, | ||
slim = false, | ||
className, | ||
...sectionProps | ||
}: SiteAlertProps & JSX.IntrinsicElements['section']): React.ReactElement => { | ||
const classes = classnames( | ||
'usa-site-alert', | ||
{ | ||
'usa-site-alert--info': variant === 'info', | ||
'usa-site-alert--emergency': variant === 'emergency', | ||
'usa-site-alert--no-heading': heading === undefined && !slim, | ||
'usa-site-alert--no-icon': !showIcon, | ||
'usa-site-alert--slim': slim, | ||
}, | ||
className | ||
) | ||
return ( | ||
<section | ||
data-testid="siteAlert" | ||
className={classes} | ||
aria-label="Site alert" | ||
{...sectionProps}> | ||
<div className="usa-alert"> | ||
<div className="usa-alert__body"> | ||
{heading && <h3 className="usa-alert__heading">{heading}</h3>} | ||
{children} | ||
</div> | ||
</div> | ||
</section> | ||
) | ||
} | ||
|
||
export default SiteAlert |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters