Skip to content

Commit

Permalink
Accessibility Updates (#4683)
Browse files Browse the repository at this point in the history
## Description

This PR implements improvements following an accessibility sweep of the
home page, and includes the following fixes and improvements:

* significant reworking of the carousel's tab handling; it now handles
switching between slides by tab graciously regardless of the content.
 * addition of aria labels and corrections to existing aria labels.
* the media text component can now take an optional alt prop in lieu of
(or in addition to) the title, with at least one of them being required.
* The headers in the rich menus are adjusted to better match the
hierarchy.
 * tab outlines are fixed for the main menu.
* Ids that could be duplicated have been removed. In the case of the
search bar, we could not remove the id at this stage (because it is tied
to downstream functionality) but we are now selectively rendering the
mobile and desktop menu to prevent the duplicate id. To facilitate this
selective rendering, we have added a breakpoints hook that allows us to
apply Bootstrap-like media queries on the TypeScript side. This
breakpoints hook may proof to be a generally useful utility.

---------

Co-authored-by: Jennifer Blumberg <[email protected]>
Co-authored-by: Pablo Noel <[email protected]>
  • Loading branch information
3 people authored Oct 31, 2024
1 parent 60a4f5f commit ac8fdad
Show file tree
Hide file tree
Showing 16 changed files with 299 additions and 117 deletions.
4 changes: 2 additions & 2 deletions static/css/base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ $headings-font-weight: 600;

/*
If the grid-breakpoints change, the TypeScript equivalent should be updated:
`static/js/apps/base/utilities/utilities.ts`, `export const BREAKPOINTS`
`static/js/shared/hooks/breakpoints.tsx`, `export const BREAKPOINTS`
*/
$grid-breakpoints: (
xs: 0,
Expand Down Expand Up @@ -160,7 +160,7 @@ $headings-font-family: $font-family-sans-serif;
background: var(--gm-3-white);
}

#main-header #main-header-logo {
#main-header .main-header-logo {
display: flex;
align-items: center;
img {
Expand Down
49 changes: 26 additions & 23 deletions static/css/core.scss
Original file line number Diff line number Diff line change
Expand Up @@ -151,17 +151,16 @@ section {

li {
display: flex;
align-items: stretch;
align-items: center;
margin: 0;
padding: 0;

.menu-main-button {
border: 0;
padding: 0;
padding: 8px 0;
margin: 0;
display: flex;
align-items: center;
height: 100%;
background-color: transparent;
.menu-main-label {
font-size: 0.875rem;
Expand All @@ -185,7 +184,7 @@ section {
.menu-main-link {
display: flex;
align-items: center;
height: 100%;
padding: 8px 0;
color: #474747;
transition: color 0.3s ease-in-out;
font-size: 0.875rem;
Expand Down Expand Up @@ -244,15 +243,17 @@ section {
font-size: 1.4rem;
font-weight: 100;
}
h4 {
font-family: $font-family-google-title;
font-size: 1rem;
text-transform: uppercase;
color: #5e5e5e;
font-weight: 300;
margin: 0 0 32px 0;
.group {
h3 {
font-family: $font-family-google-title;
font-size: 1rem;
text-transform: uppercase;
color: #5e5e5e;
font-weight: 300;
margin: 0 0 32px 0;
}
}
h5 {
h4 {
font-family: $font-family-google-title;
font-size: 1rem;
font-weight: 500;
Expand Down Expand Up @@ -504,14 +505,16 @@ section {
font-size: 1.4rem;
font-weight: 100;
}
h4 {
font-family: $font-family-google-title;
font-size: 1rem;
text-transform: uppercase;
color: #5e5e5e;
font-weight: 300;
.group {
h3 {
font-family: $font-family-google-title;
font-size: 1rem;
text-transform: uppercase;
color: #5e5e5e;
font-weight: 300;
}
}
h5 {
h4 {
font-family: $font-family-google-title;
font-size: 1rem;
font-weight: 500;
Expand Down Expand Up @@ -603,8 +606,8 @@ section {

.search-input-text {
display: block;
padding: 0px;
margin: 0px;
padding: 0;
margin: 0;
width: 150px;
flex-grow: 10;
height: 38px;
Expand Down Expand Up @@ -657,7 +660,7 @@ section {
.search-input-result-section {
display: flex;
flex-direction: column;
padding: 10px 0px;
padding: 10px 0;

.search-input-result {
display: flex;
Expand All @@ -682,7 +685,7 @@ section {
}

.result-divider {
margin: 0px;
margin: 0;
}
}

Expand Down
7 changes: 5 additions & 2 deletions static/js/apps/base/components/header_bar/header_bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import React, { ReactElement } from "react";

import { useBreakpoints } from "../../../../shared/hooks/breakpoints";
import { HeaderMenu, Labels, Routes } from "../../../../shared/types/base";
import HeaderBarSearch from "./header_bar_search";
import HeaderLogo from "./header_logo";
Expand Down Expand Up @@ -52,6 +53,8 @@ const HeaderBar = ({
labels,
routes,
}: HeaderBarProps): ReactElement => {
const { up, down } = useBreakpoints();

return (
<div id="main-header-container">
<nav id="main-nav">
Expand All @@ -63,7 +66,7 @@ const HeaderBar = ({
labels={labels}
routes={routes}
/>
{showHeaderSearchBar && <HeaderBarSearch />}
{showHeaderSearchBar && up("lg") && <HeaderBarSearch />}
<MenuDesktop menu={menu} labels={labels} routes={routes} />
</div>
<div className="navbar-menu-mobile">
Expand All @@ -74,7 +77,7 @@ const HeaderBar = ({
labels={labels}
routes={routes}
/>
{showHeaderSearchBar && <HeaderBarSearch />}
{showHeaderSearchBar && down("md") && <HeaderBarSearch />}
<MenuMobile menu={menu} labels={labels} routes={routes} />
</div>
</nav>
Expand Down
10 changes: 8 additions & 2 deletions static/js/apps/base/components/header_bar/header_bar_search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,17 @@ import {
triggerGAEvent,
} from "../../../../shared/ga_events";

const HeaderBarSearch = (): ReactElement => {
interface HeaderBarSearchProps {
inputId?: string;
}

const HeaderBarSearch = ({
inputId = "query-search-input",
}: HeaderBarSearchProps): ReactElement => {
return (
<NlSearchBar
variant="header-inline"
inputId="query-search-input"
inputId={inputId}
onSearch={(q): void => {
triggerGAEvent(GA_EVENT_NL_SEARCH, {
[GA_PARAM_QUERY]: q,
Expand Down
2 changes: 1 addition & 1 deletion static/js/apps/base/components/header_bar/header_logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const HeaderLogo = ({
return (
<div className="navbar-brand">
{logoPath && (
<div id="main-header-logo">
<div className="main-header-logo">
<a
href={routes["static.homepage"]}
aria-label={labels["Back to homepage"]}
Expand Down
123 changes: 66 additions & 57 deletions static/js/apps/base/components/header_bar/menu_desktop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,68 +93,77 @@ const MenuDesktop = ({
return (
<div className="header-menu" ref={menuContainerRef}>
<ul className="header-menu-list">
{menu.map((menuItem, index) => (
<li key={menuItem.label}>
{menuItem.url ? (
<a
className="menu-main-link"
href={resolveHref(menuItem.url, routes)}
onClick={() => {
triggerGAEvent(GA_EVENT_HEADER_CLICK, {
[GA_PARAM_ID]: `desktop main ${menuItem.id}`,
[GA_PARAM_URL]: menuItem.url,
});
return true;
}}
>
{labels[menuItem.label]}
</a>
) : (
<>
<button
className="menu-main-button"
onClick={(): void => {
{menu.map((menuItem, index) => {
const buttonId = slugify(`nav-${menuItem.label}-button`);
const dropdownId = slugify(`nav-${menuItem.label}-dropdown`);

return (
<li key={menuItem.label}>
{menuItem.url ? (
<a
className="menu-main-link"
href={resolveHref(menuItem.url, routes)}
onClick={() => {
triggerGAEvent(GA_EVENT_HEADER_CLICK, {
[GA_PARAM_ID]: `desktop ${menuItem.id}`,
[GA_PARAM_ID]: `desktop main ${menuItem.id}`,
[GA_PARAM_URL]: menuItem.url,
});
return !menuItem.url && toggleMenu(index);
}}
onTouchEnd={(e): void => {
if (!menuItem.url) itemMenuTouch(e, index);
return true;
}}
>
<span className="menu-main-label">
{labels[menuItem.label]}
</span>
<span
className={`material-icons-outlined menu-arrow-icon ${
openMenu === index ? "open" : ""
}`}
{labels[menuItem.label]}
</a>
) : (
<>
<button
id={buttonId}
className="menu-main-button"
onClick={(): void => {
triggerGAEvent(GA_EVENT_HEADER_CLICK, {
[GA_PARAM_ID]: `desktop ${menuItem.id}`,
});
return !menuItem.url && toggleMenu(index);
}}
onTouchEnd={(e): void => {
if (!menuItem.url) itemMenuTouch(e, index);
}}
aria-expanded={openMenu === index}
aria-controls={dropdownId}
>
keyboard_arrow_down
</span>
</button>
<div
ref={(el: HTMLDivElement | null): void => {
submenuRefs.current[index] = el;
}}
className="rich-menu-container"
aria-labelledby={slugify(`nav-${menuItem.label}-dropdown`)}
style={{
maxHeight: openMenu === index ? `${panelHeight}px` : 0,
}}
>
<MenuDesktopRichMenu
menuItem={menuItem}
labels={labels}
routes={routes}
open={openMenu === index}
/>
</div>
</>
)}
</li>
))}
<span className="menu-main-label">
{labels[menuItem.label]}
</span>
<span
className={`material-icons-outlined menu-arrow-icon ${
openMenu === index ? "open" : ""
}`}
>
keyboard_arrow_down
</span>
</button>
<div
ref={(el: HTMLDivElement | null): void => {
submenuRefs.current[index] = el;
}}
id={dropdownId}
className="rich-menu-container"
aria-labelledby={buttonId}
style={{
maxHeight: openMenu === index ? `${panelHeight}px` : 0,
}}
>
<MenuDesktopRichMenu
menuItem={menuItem}
labels={labels}
routes={routes}
open={openMenu === index}
/>
</div>
</>
)}
</li>
);
})}
</ul>
<div className={"panel"} style={{ height: panelHeight }} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ const MenuRichSectionGroup = ({

return (
<div className={"group"}>
{menuGroup.title && <h4>{menuGroup.title}</h4>}
{menuGroup.title && <h3>{menuGroup.title}</h3>}
{menuGroup.items.map((item, index) => (
<div key={index} className={"item"}>
{item.title && item.url ? (
<h5>
<h4>
<a
href={resolveHref(item.url, routes)}
className={"item-link"}
onClick={() => {
onClick={(): boolean => {
triggerGAEvent(GA_EVENT_HEADER_CLICK, {
[GA_PARAM_ID]: `${type} submenu ${menuGroup.id}-${index}`,
[GA_PARAM_URL]: item.url,
Expand All @@ -74,7 +74,7 @@ const MenuRichSectionGroup = ({
)}
{item.title}
</a>
</h5>
</h4>
) : (
<h5>{item.title}</h5>
)}
Expand Down
17 changes: 0 additions & 17 deletions static/js/apps/base/utilities/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,20 +139,3 @@ export const extractLabels = (elementId = "metadata-labels"): Labels => {

return labels;
};

/*
A breakpoints constant object for responsiveness, for access on the TypeScript side.
These are the default breakpoints for a page that does not have custom breakpoints and are
applied in: `static/css/base.scss`
If a page does not use default breakpoints and those breakpoints are required on
the TypeScript side, a separate breakpoint object should be created.
*/
export const BREAKPOINTS = {
xs: 0,
sm: 576,
md: 768,
lg: 1068,
xl: 1350,
xxl: 1400,
};
2 changes: 1 addition & 1 deletion static/js/apps/homepage/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

/**
* Entry point for Version 2 of the home page.
* Entry point for the home page.
*/

import React from "react";
Expand Down
1 change: 1 addition & 0 deletions static/js/build/one_data_commons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const OneDataCommons = (): ReactElement => {
return [
<MediaText
key={0}
alt={"One Data Commons Website Screenshot"}
mediaType="image"
mediaSource="images/content/build/ONEData.png"
>
Expand Down
Loading

0 comments on commit ac8fdad

Please sign in to comment.