Skip to content

Commit

Permalink
Fix nav header accessibility issues
Browse files Browse the repository at this point in the history
  • Loading branch information
emyl3 committed Sep 12, 2023
1 parent 2b24fc8 commit 469fc91
Show file tree
Hide file tree
Showing 6 changed files with 385 additions and 14 deletions.
14 changes: 8 additions & 6 deletions frontend/src/app/commonComponents/ChangeUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ const ChangeUser = () => {
}

const getLink = (email: string, name: string) => (
<a
className="ghost-user-link"
href={`/#access_token=SR-DEMO-LOGIN%20${email}`}
>
Login as {name}
</a>
<li>
<a
className="ghost-user-link"
href={`/#access_token=SR-DEMO-LOGIN%20${email}`}
>
Login as {name}
</a>
</li>
);

return (
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/app/commonComponents/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface Option {
interface Props {
options: Option[];
label?: string | React.ReactNode;
ariaLabel?: string;
name?: string;
onChange?: (e: React.ChangeEvent<HTMLSelectElement>) => void;
selectedValue: string;
Expand All @@ -36,6 +37,7 @@ type SelectProps = JSX.IntrinsicElements["select"];
const Dropdown: React.FC<Props & SelectProps> = ({
options,
label,
ariaLabel,
name,
onChange,
disabled,
Expand Down Expand Up @@ -91,6 +93,7 @@ const Dropdown: React.FC<Props & SelectProps> = ({
)}
name={name}
id={id}
aria-label={ariaLabel}
aria-required={required || "false"}
onChange={onChange}
value={selectedValue || defaultOption || ""}
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/app/commonComponents/Header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@

.role-tag {
// $theme-color-prime-gray:
padding-bottom: 1rem;
color: #71767a;
margin-top: 0.5rem;
border-bottom: 1px #dfe1e2 solid;
}

.header-link-icon {
Expand Down Expand Up @@ -100,7 +102,7 @@
.navlink__support {
display: flex;
align-items: center;
margin-top: 0.75rem !important;
margin-top: 0.75rem;

button {
color: #005ea2;
Expand Down
56 changes: 56 additions & 0 deletions frontend/src/app/commonComponents/Header.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { render } from "@testing-library/react";
import "../../i18n";
import { Provider } from "react-redux";
import { MemoryRouter } from "react-router-dom";
import { MockedProvider } from "@apollo/client/testing";
import configureStore from "redux-mock-store";
import { configureAxe } from "jest-axe";

import Header from "./Header";

const axe = configureAxe({
rules: {
// disable landmark rules when testing isolated components.
region: { enabled: false },
},
});
const mockStore = configureStore([]);
const store = mockStore({
organization: {
name: "Organization Name",
},
user: {
firstName: "Kim",
lastName: "Mendoza",
roleDescription: "Admin user",
},
facilities: [
{ id: "1", name: "Facility One" },
{ id: "2", name: "Facility Two" },
],
});

const mockNavigate = jest.fn();
jest.mock("react-router-dom", () => {
const original = jest.requireActual("react-router-dom");
return {
...original,
useNavigate: () => mockNavigate,
};
});

describe("Header", () => {
it("displays correctly", async () => {
render(
<Provider store={store}>
<MockedProvider>
<MemoryRouter>
<Header />
</MemoryRouter>
</MockedProvider>
</Provider>
);
expect(document.body).toMatchSnapshot();
expect(await axe(document.body)).toHaveNoViolations();
});
});
20 changes: 13 additions & 7 deletions frontend/src/app/commonComponents/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ const Header: React.FC<{}> = () => {
<li className="usa-sidenav__item role-tag">
{formatRole(user.roleDescription)}
</li>
<hr />
<li className="usa-sidenav__item navlink__support">
<div className="header-link-icon sparkle-icon-mask"></div>
<a
Expand Down Expand Up @@ -281,15 +280,23 @@ const Header: React.FC<{}> = () => {
className={item.className}
data-testid={`${deviceType}-${item.dataTestId}`}
id={`${deviceType}-${item.dataTestId}`}
role={item.hasSubmenu ? "button" : "link"}
aria-expanded={item.hasSubmenu ? staffDetailsVisible : undefined}
aria-controls={
item.hasSubmenu
? `${deviceType}-${item.dataTestId}-submenu`
: undefined
}
>
{deviceType === "desktop" ? item.icon : item.mobileDisplayText}
</LinkWithQuery>
{item.hasSubmenu &&
staffDetailsVisible &&
deviceType === "desktop" ? (
<div
id={`${deviceType}-${item.dataTestId}-submenu`}
ref={staffDefailsRef}
aria-label="Primary navigation"
aria-label="Account navigation"
className={classNames("prime-staff-infobox", {
"is-prime-staff-infobox-visible": staffDetailsVisible,
})}
Expand Down Expand Up @@ -326,7 +333,7 @@ const Header: React.FC<{}> = () => {
</button>

<nav
aria-label="Primary navigation"
aria-label="Primary mobile navigation"
className={classNames(
"usa-nav",
"prime-nav",
Expand All @@ -350,13 +357,12 @@ const Header: React.FC<{}> = () => {
</ul>
<div className="usa-nav__primary mobile-sublist-container">
{secondaryNavSublist("mobile")}
<hr />

<label id="mobile-facility-label" className="usa-label ">
Facility
</label>
<div className="prime-facility-select facility-select-mobile-container">
<Dropdown
ariaLabel="Select testing facility"
selectedValue={facility.id}
onChange={onFacilitySelect}
className={"mobile-facility-select"}
Expand All @@ -373,14 +379,14 @@ const Header: React.FC<{}> = () => {
</div>

<nav
aria-label="Primary navigation"
aria-label="Primary desktop navigation"
className="usa-nav prime-nav desktop-nav"
>
{mainNavList("desktop")}
{facilities && facilities.length > 0 ? (
<div className="prime-facility-select">
<Dropdown
aria-label={"Select facility"}
ariaLabel="Select testing facility"
selectedValue={facility.id}
onChange={onFacilitySelect}
options={facilities.map(({ name, id }) => ({
Expand Down
Loading

0 comments on commit 469fc91

Please sign in to comment.