Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: upgrade to USWDS 3.8.1 #2848

Open
wants to merge 42 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
3f87e54
adds a11y testing package, runner, and gh action
werdnanoslen Mar 9, 2024
7b3c752
Require aria-hidden/label on Icons, small fix to story's size control
werdnanoslen Mar 12, 2024
086b47e
applied previous commit changes to Icons.stories as well
werdnanoslen Mar 12, 2024
4e9ead6
Added label to all select stories, other minor fixes and improvements
werdnanoslen Mar 12, 2024
11991a2
change card header from semantic header to div
werdnanoslen Mar 13, 2024
918a01f
change tag story color and className to fix a11y violation
werdnanoslen Mar 13, 2024
055a649
added bg-ink to text styles that didn't pass a11y on white bg
werdnanoslen Mar 13, 2024
8b2ca43
Added labels to all TextInput stories to fix a11y warnings there, and…
werdnanoslen Mar 13, 2024
15ba009
Added label to all RangeInput stories, other minor fixes and improvem…
werdnanoslen Mar 13, 2024
c7cf59a
hide SocialLinks' decorative svgs from SRs
werdnanoslen Mar 14, 2024
944fb58
Added label to all textarea stories, tidied
werdnanoslen Mar 14, 2024
4e117b8
added aria-hidden="true" to all decorative IconListIcon stories
werdnanoslen Mar 14, 2024
2e2e371
Added label to all prefix/suffix stories, tidied
werdnanoslen Mar 14, 2024
f73bbcb
Added label to all DatePicker stories, tidied
werdnanoslen Mar 14, 2024
54addb4
aria-hide decorative icon in search button
werdnanoslen Mar 15, 2024
05c6842
changed Footers' h3 to p elements — class already handles styling
werdnanoslen Mar 15, 2024
2cb2456
removed test that shouldn't exist given a11y context
werdnanoslen Mar 15, 2024
b436f93
aria-hid Pagination Icons, tidied stories
werdnanoslen Mar 15, 2024
aa499a8
replaced presentaiton role with aria-label to fix a11y issue
werdnanoslen Mar 15, 2024
e8fd227
disabled skip-link rule for ExtendedNav, out of context
werdnanoslen Mar 15, 2024
d35dc87
use aria-controls only when appropriate
werdnanoslen Mar 15, 2024
f94b1cb
allow local rules to apply
werdnanoslen Mar 15, 2024
0ae68d9
Merge branch 'an-storybooka11y' into an-storybooka11y-fixes
werdnanoslen Mar 15, 2024
904f711
Merge branch 'main' into an-storybooka11y-fixes
werdnanoslen Mar 15, 2024
12a8688
check a11y after building storybook
werdnanoslen Mar 15, 2024
86f210b
Merge branch 'an-storybooka11y-fixes' of github.com:trussworks/react-…
werdnanoslen Mar 15, 2024
db09b00
removed CI, moving to another branch
werdnanoslen Mar 15, 2024
83fff72
Merge branch 'main' into an-storybooka11y-fixes
werdnanoslen Mar 15, 2024
69a93f6
update uswds package
werdnanoslen Mar 22, 2024
6039237
Added styles for indeterminate checkboxes
werdnanoslen Mar 22, 2024
339a37a
Added styles for indeterminate radios
werdnanoslen Mar 22, 2024
66b78da
Added the ability to customize which headings will be pulled into the…
werdnanoslen Mar 25, 2024
53d6f50
change class name and selection criteria for bolded heading
werdnanoslen Mar 25, 2024
3a929a9
Added a sticky header variant to the table component
werdnanoslen May 10, 2024
2372e71
prettier
werdnanoslen May 10, 2024
da8625d
updated sidenav example in documentation per new theme setting
werdnanoslen May 13, 2024
15215dc
Merge branch 'main' into an-3.8.0
werdnanoslen Jun 20, 2024
c9e4973
Make tooltip content hoverable
werdnanoslen Jun 24, 2024
b4fc992
upgrade uswds
werdnanoslen Jun 24, 2024
35d84e2
Make tooltip dismissible with escape key
werdnanoslen Jun 24, 2024
f11255b
Merge branch 'main' into an-3.8.0
werdnanoslen Jun 24, 2024
e99a67d
Merge branch 'an-3.8.1' into an-3.8.0
werdnanoslen Jun 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
},
"homepage": "https://github.com/trussworks/react-uswds#readme",
"peerDependencies": {
"@uswds/uswds": "^3.7.1",
"@uswds/uswds": "^3.8.1",
"focus-trap-react": "^10.2.3",
"react": "^16.x || ^17.x || ^18.x",
"react-dom": "^16.x || ^17.x || ^18.x"
Expand Down Expand Up @@ -98,7 +98,7 @@
"@types/react-test-renderer": "^18.0.7",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.1.1",
"@uswds/uswds": "3.7.1",
"@uswds/uswds": "3.8.1",
"@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-istanbul": "^1.2.1",
"all-contributors-cli": "^6.24.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,17 @@ export default {
title: {
control: 'text',
},
headingElements: {
control: 'check',
options: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
},
},
args: {
headingLevel: 'h4',
rootMargin: '0px 0px 0px 0px',
threshold: 1,
title: 'On this page',
headingElements: ['h2', 'h3'],
},
parameters: {
docs: {
Expand All @@ -46,6 +51,7 @@ type StorybookArguments = {
scrollOffset: string
threshold: number
title: string
headingElements: HeadingLevel[]
}

export const Default = (argTypes: StorybookArguments): React.ReactElement => (
Expand All @@ -56,6 +62,7 @@ export const Default = (argTypes: StorybookArguments): React.ReactElement => (
rootMargin={argTypes.rootMargin}
threshold={argTypes.threshold}
title={argTypes.title}
headingElements={argTypes.headingElements}
/>
)

Expand All @@ -72,5 +79,6 @@ export const ScrollOffset = (
scrollOffset="2rem"
threshold={argTypes.threshold}
title={argTypes.title}
headingElements={argTypes.headingElements}
/>
)
23 changes: 21 additions & 2 deletions src/components/InPageNavigation/InPageNavigation.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { screen, render, getByRole } from '@testing-library/react'
import { screen, render, getByRole, within } from '@testing-library/react'
import { userEvent } from '@testing-library/user-event'
import { InPageNavigation } from './InPageNavigation'
import { HeadingLevel } from '../../types/headingLevel'
Expand All @@ -13,14 +13,15 @@ describe('InPageNavigation component', () => {
title: 'What do we have <i>here</i>?',
}

const setup = (plain?: boolean) => {
const setup = (plain?: boolean, headingElements?: HeadingLevel[]) => {
const utils = plain
? render(<InPageNavigation content={props.content} />)
: render(
<InPageNavigation
content={props.content}
headingLevel={props.headingLevel}
title={props.title}
headingElements={headingElements}
/>
)
const nav = screen.getByTestId('InPageNavigation')
Expand Down Expand Up @@ -62,4 +63,22 @@ describe('InPageNavigation component', () => {
})
expect(heading).toBeInTheDocument()
})

describe('lists the right heading types if', () => {
it('is undefined', () => {
const { nav } = setup(true)
const contentHeadingsTwo = screen.getAllByRole('heading', { level: 2 })
const contentHeadingsThree = screen.getAllByRole('heading', { level: 3 })
const contentHeadings = contentHeadingsTwo.concat(contentHeadingsThree)
const headingLinks = within(nav).getAllByRole('link')
expect(contentHeadings.length).toBe(headingLinks.length)
})

it('is defined', () => {
const { nav } = setup(false, ['h2' as HeadingLevel])
const contentHeadingsTwo = screen.getAllByRole('heading', { level: 2 })
const headingLinks = within(nav).getAllByRole('link')
expect(contentHeadingsTwo.length).toBe(headingLinks.length)
})
})
})
8 changes: 6 additions & 2 deletions src/components/InPageNavigation/InPageNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type InPageNavigationProps = {
scrollOffset?: string
threshold?: number
title?: string
headingElements?: HeadingLevel[]
}

export const InPageNavigation = ({
Expand All @@ -26,6 +27,7 @@ export const InPageNavigation = ({
scrollOffset,
threshold = 1,
title = 'On this page',
headingElements = ['h2', 'h3'],
...divProps
}: InPageNavigationProps &
Omit<JSX.IntrinsicElements['div'], 'content'>): React.ReactElement => {
Expand All @@ -39,8 +41,9 @@ export const InPageNavigation = ({
'--margin-offset': scrollOffset,
} as React.CSSProperties
const [currentSection, setCurrentSection] = useState('')
if (headingElements.length === 0) headingElements = ['h2', 'h3']
const sectionHeadings: JSX.Element[] = content.props.children.filter(
(el: JSX.Element) => el.type === 'h2' || el.type === 'h3'
(el: JSX.Element) => headingElements.includes(el.type)
)
const handleIntersection = (entries: IntersectionObserverEntry[]) => {
entries.forEach((entry) => {
Expand Down Expand Up @@ -78,7 +81,8 @@ export const InPageNavigation = ({
const heading: JSX.Element = el.props.children
const href: string = el.props.id
const hClass = classnames('usa-in-page-nav__item', {
'usa-in-page-nav__item--sub-item': el.type === 'h3',
'usa-in-page-nav__item--primary':
el.type === headingElements[0],
})
const lClass = classnames('usa-in-page-nav__link', {
'usa-current': href === currentSection,
Expand Down
19 changes: 17 additions & 2 deletions src/components/Table/Table.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,15 @@ Source: https://designsystem.digital.gov/components/table/
stackedStyle: {
control: {
type: 'select',
options: ['default', 'headers'],
options: ['default', 'headers', 'none'],
},
},
stickyHeader: {
control: {
type: 'boolean',
},
description: 'This is not compatible with stacked and scrollable',
},
},
args: {
stackedStyle: 'default',
Expand All @@ -41,7 +47,8 @@ Source: https://designsystem.digital.gov/components/table/
type StorybookArguments = {
bordered: boolean
striped: boolean
stackedStyle: 'default' | 'headers'
stackedStyle: 'default' | 'headers' | 'none'
stickyHeader: boolean
}

const testContent = (
Expand Down Expand Up @@ -343,6 +350,14 @@ export const Scrollable = (): React.ReactElement => (
</>
)

export const StickyHeader = {
render: (argTypes: StorybookArguments): React.ReactElement => (
<Table stickyHeader={argTypes.stickyHeader} bordered={argTypes.bordered}>
{testContent}
</Table>
),
}

export const Striped = {
render: (argTypes: StorybookArguments): React.ReactElement => (
<Table
Expand Down
6 changes: 6 additions & 0 deletions src/components/Table/Table.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ describe('Table component', () => {
)
})

it('renders sticky header table', () => {
const { getByRole } = render(<Table stickyHeader>{testContent}</Table>)

expect(getByRole('table')).toHaveClass('usa-table--sticky-header')
})

it('passes the class onto the root table element', () => {
const { getByRole } = render(
<Table className="custom-class">{testContent}</Table>
Expand Down
9 changes: 9 additions & 0 deletions src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type TableProps = {
striped?: boolean
compact?: boolean
stackedStyle?: 'none' | 'default' | 'headers'
stickyHeader?: boolean
}

export const Table = ({
Expand All @@ -27,6 +28,7 @@ export const Table = ({
striped,
compact,
stackedStyle = 'none',
stickyHeader,
}: TableProps): React.ReactElement => {
const classes = classnames(
'usa-table',
Expand All @@ -38,6 +40,7 @@ export const Table = ({
'usa-table--compact': compact,
'usa-table--stacked': stackedStyle === 'default',
'usa-table--stacked-header': stackedStyle === 'headers',
'usa-table--sticky-header': stickyHeader,
},
className
)
Expand All @@ -48,6 +51,12 @@ export const Table = ({
)
}

if (stickyHeader && (scrollable || stackedStyle !== 'none')) {
console.warn(
'USWDS states that sticky headers are not compatible with scrollable or stacked variants. See USWDS Table component, Table variants for more information: https://designsystem.digital.gov/components/table'
)
}

const table = (
<table className={classes} data-testid="table">
{caption && <caption>{caption}</caption>}
Expand Down
9 changes: 7 additions & 2 deletions src/components/Tooltip/Tooltip.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ describe('Tooltip component', () => {
expect(bodyEl).toHaveClass('is-visible')
expect(bodyEl).toHaveAttribute('aria-hidden', 'false')

fireEvent.mouseLeave(screen.getByTestId('triggerElement'))
fireEvent.mouseLeave(screen.getByTestId('tooltipWrapper'))
expect(bodyEl).not.toHaveClass('is-visible')
expect(bodyEl).toHaveAttribute('aria-hidden', 'true')
})
Expand Down Expand Up @@ -110,14 +110,19 @@ describe('Tooltip component', () => {
expect(bodyEl).toHaveAttribute('aria-hidden', 'true')
})

it('hides tooltip on keydown after focus', () => {
it('hides tooltip on Escape keydown after focus', () => {
render(<Tooltip label="Click me">My Tooltip</Tooltip>)
const bodyEl = screen.queryByRole('tooltip', { hidden: true })

fireEvent.focus(screen.getByTestId('triggerElement'))
expect(bodyEl).toHaveClass('is-visible')
expect(bodyEl).toHaveAttribute('aria-hidden', 'false')

fireEvent.keyDown(screen.getByTestId('triggerElement'), { key: 'a' })

expect(bodyEl).toHaveClass('is-visible')
expect(bodyEl).not.toHaveAttribute('aria-hidden', 'true')

fireEvent.keyDown(screen.getByTestId('triggerElement'), { key: 'Escape' })

expect(bodyEl).not.toHaveClass('is-visible')
Expand Down
19 changes: 13 additions & 6 deletions src/components/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ export function Tooltip<
const hideTooltip = (): void => {
setVisible(false)
}
const escapeTooltip = (e: React.KeyboardEvent<HTMLButtonElement>): void => {
if (e.key === 'Escape') hideTooltip()
}

const wrapperClasses = classnames('usa-tooltip', wrapperclasses)

Expand Down Expand Up @@ -220,16 +223,18 @@ export function Tooltip<
onMouseEnter: showTooltip,
onMouseOver: showTooltip,
onFocus: showTooltip,
onMouseLeave: hideTooltip,
onBlur: hideTooltip,
onKeyDown: hideTooltip,
onKeyDown: escapeTooltip,
className: triggerClasses,
},
children
)

return (
<span data-testid="tooltipWrapper" className={wrapperClasses}>
<span
data-testid="tooltipWrapper"
className={wrapperClasses}
onMouseLeave={hideTooltip}>
{triggerElement}
<span
data-testid="tooltipBody"
Expand All @@ -254,7 +259,10 @@ export function Tooltip<
)

return (
<span data-testid="tooltipWrapper" className={wrapperClasses}>
<span
data-testid="tooltipWrapper"
className={wrapperClasses}
onMouseLeave={hideTooltip}>
<button
{...remainingProps}
data-testid="triggerElement"
Expand All @@ -267,9 +275,8 @@ export function Tooltip<
onMouseEnter={showTooltip}
onMouseOver={showTooltip}
onFocus={showTooltip}
onMouseLeave={hideTooltip}
onBlur={hideTooltip}
onKeyDown={hideTooltip}>
onKeyDown={escapeTooltip}>
{children}
</button>
<span
Expand Down
Loading
Loading