fix(a11y): make breadcrumb nav more accessible (#45021)
* fix: make breadcrumb nav more accessible * refactor: cypress test and jest snapshot * slight adjustment to left breadcrumb focus outline * feat: translate aria for nav * chore(tools): update snapshot Co-authored-by: ahmad abdolsaheb <ahmad.abdolsaheb@gmail.com> Co-authored-by: Naomi Carrigan <nhcarrigan@gmail.com>
This commit is contained in:
@ -466,7 +466,9 @@
|
||||
"first-page": "Go to first page",
|
||||
"previous-page": "Go to previous page",
|
||||
"next-page": "Go to next page",
|
||||
"last-page": "Go to last page"
|
||||
"last-page": "Go to last page",
|
||||
"primary-nav": "primary",
|
||||
"breadcrumb-nav": "breadcrumb"
|
||||
},
|
||||
"flash": {
|
||||
"honest-first": "To claim a certification, you must first accept our academic honesty policy",
|
||||
|
@ -5,6 +5,7 @@
|
||||
// @ts-nocheck
|
||||
import Loadable from '@loadable/component';
|
||||
import React, { Ref } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { isLanding } from '../../../utils/path-parsers';
|
||||
import { Link, SkeletonSprite } from '../../helpers';
|
||||
import MenuButton from './menu-button';
|
||||
@ -34,6 +35,7 @@ export const UniversalNav = ({
|
||||
fetchState
|
||||
}: UniversalNavProps): JSX.Element => {
|
||||
const { pending } = fetchState;
|
||||
const { t } = useTranslation();
|
||||
|
||||
const search =
|
||||
typeof window !== `undefined` && isLanding(window.location.pathname) ? (
|
||||
@ -44,6 +46,7 @@ export const UniversalNav = ({
|
||||
|
||||
return (
|
||||
<nav
|
||||
aria-label={t('aria.primary-nav')}
|
||||
className={'universal-nav' + (displayMenu ? ' expand-nav' : '')}
|
||||
id='universal-nav'
|
||||
>
|
||||
|
@ -4,11 +4,15 @@ exports[`<ChallengeTitle/> renders correctly 1`] = `
|
||||
<div
|
||||
className="challenge-title-wrap"
|
||||
>
|
||||
<div
|
||||
<nav
|
||||
aria-label="aria.breadcrumb-nav"
|
||||
className="challenge-title-breadcrumbs"
|
||||
>
|
||||
<a
|
||||
<ol>
|
||||
<li
|
||||
className="breadcrumb-left"
|
||||
>
|
||||
<a
|
||||
href="/learn/fake-superblock"
|
||||
state={
|
||||
Object {
|
||||
@ -20,11 +24,11 @@ exports[`<ChallengeTitle/> renders correctly 1`] = `
|
||||
className="ellipsis"
|
||||
/>
|
||||
</a>
|
||||
<div
|
||||
className="breadcrumb-center"
|
||||
/>
|
||||
<a
|
||||
</li>
|
||||
<li
|
||||
className="breadcrumb-right"
|
||||
>
|
||||
<a
|
||||
href="/learn/fake-superblock/#fake-block"
|
||||
state={
|
||||
Object {
|
||||
@ -32,7 +36,9 @@ exports[`<ChallengeTitle/> renders correctly 1`] = `
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<div
|
||||
className="challenge-title"
|
||||
>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import i18next from 'i18next';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from '../../../components/helpers/index';
|
||||
|
||||
import './challenge-title.css';
|
||||
@ -10,10 +11,15 @@ interface BreadCrumbProps {
|
||||
}
|
||||
|
||||
function BreadCrumb({ block, superBlock }: BreadCrumbProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div className='challenge-title-breadcrumbs'>
|
||||
<nav
|
||||
className='challenge-title-breadcrumbs'
|
||||
aria-label={t('aria.breadcrumb-nav')}
|
||||
>
|
||||
<ol>
|
||||
<li className='breadcrumb-left'>
|
||||
<Link
|
||||
className='breadcrumb-left'
|
||||
state={{ breadcrumbBlockClick: block }}
|
||||
to={`/learn/${superBlock}`}
|
||||
>
|
||||
@ -21,15 +27,17 @@ function BreadCrumb({ block, superBlock }: BreadCrumbProps): JSX.Element {
|
||||
{i18next.t(`intro:${superBlock}.title`)}
|
||||
</span>
|
||||
</Link>
|
||||
<div className='breadcrumb-center' />
|
||||
</li>
|
||||
<li className='breadcrumb-right'>
|
||||
<Link
|
||||
className='breadcrumb-right'
|
||||
state={{ breadcrumbBlockClick: block }}
|
||||
to={`/learn/${superBlock}/#${block}`}
|
||||
>
|
||||
{i18next.t(`intro:${superBlock}.blocks.${block}.title`)}
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -13,39 +13,69 @@
|
||||
}
|
||||
|
||||
.challenge-title-breadcrumbs {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
font-size: 16px;
|
||||
border: 1px solid var(--quaternary-background);
|
||||
height: 25px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.challenge-title-breadcrumbs ol {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
list-style-type: none;
|
||||
margin-bottom: 0;
|
||||
padding-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.challenge-title-breadcrumbs ol a {
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
.challenge-title-breadcrumbs ol a:focus {
|
||||
outline: 2px solid var(--secondary-color);
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.challenge-title-breadcrumbs ol a:focus:not(:focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.challenge-title-breadcrumbs ol a:hover {
|
||||
background-color: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.breadcrumb-left {
|
||||
text-decoration: none;
|
||||
min-width: 25px;
|
||||
min-width: 3rem;
|
||||
display: inline-block;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-height: 25px;
|
||||
white-space: nowrap;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 2;
|
||||
background-color: var(--quaternary-background);
|
||||
padding: 0px 3px;
|
||||
padding: 0 0.57rem 0 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.breadcrumb-center {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: calc(25px / 2) solid transparent;
|
||||
border-bottom: calc(23px / 2) solid transparent;
|
||||
border-left: calc(23px / 2) solid var(--quaternary-background);
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
.breadcrumb-left:after {
|
||||
background-color: var(--secondary-background);
|
||||
content: '';
|
||||
border-top: calc(1.375rem / 2) solid transparent;
|
||||
border-bottom: calc(1.2rem / 2) solid transparent;
|
||||
border-left: calc(1.1rem / 2) solid var(--quaternary-background);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.breadcrumb-right {
|
||||
@ -53,29 +83,19 @@
|
||||
display: inline-block;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
max-height: 25px;
|
||||
min-width: 50px;
|
||||
flex-grow: 2;
|
||||
flex-shrink: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding: 0px 3px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.breadcrumb-rule {
|
||||
margin: 5px -10px;
|
||||
}
|
||||
|
||||
.breadcrumb-left:hover {
|
||||
text-decoration: underline;
|
||||
background-color: var(--quaternary-background);
|
||||
}
|
||||
.breadcrumb-right:hover {
|
||||
text-decoration: underline;
|
||||
background-color: var(--secondary-background);
|
||||
}
|
||||
|
||||
.title-text {
|
||||
text-decoration: none;
|
||||
min-width: 25px;
|
||||
|
@ -8,23 +8,23 @@ describe('The breadcumbs should work corectly', () => {
|
||||
it('It should have a superblock and a course', () => {
|
||||
cy.visit(challengeUrl);
|
||||
cy.get('.ellipsis').contains('Responsive Web Design').and('be.visible');
|
||||
cy.get('.breadcrumb-left')
|
||||
cy.get('.breadcrumb-left > a')
|
||||
.should('have.attr', 'href')
|
||||
.and('include', superBlockUrl);
|
||||
cy.get('.breadcrumb-right')
|
||||
cy.get('.breadcrumb-right > a')
|
||||
.contains('Basic HTML and HTML5')
|
||||
.and('be.visible');
|
||||
cy.get('.breadcrumb-right')
|
||||
cy.get('.breadcrumb-right > a')
|
||||
.should('have.attr', 'href')
|
||||
.and('include', courseUrl);
|
||||
});
|
||||
|
||||
it('Should redirect to the right url', () => {
|
||||
cy.visit(challengeUrl);
|
||||
cy.get('.breadcrumb-left').click();
|
||||
cy.get('.breadcrumb-left > a').click();
|
||||
cy.url().should('include', '/responsive-web-design');
|
||||
cy.visit(challengeUrl);
|
||||
cy.get('.breadcrumb-right').click();
|
||||
cy.get('.breadcrumb-right > a').click();
|
||||
cy.url().should('include', '/responsive-web-design/#basic-html-and-html5');
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user