Skip to content

Commit

Permalink
[tra-14929]Ajouter des liens d'évitement Menu principal / secondaire …
Browse files Browse the repository at this point in the history
…/ contenu (Aller à) (#3626)
  • Loading branch information
JulianaJM authored Oct 8, 2024
1 parent 6957b77 commit 926ff46
Show file tree
Hide file tree
Showing 11 changed files with 221 additions and 18 deletions.
2 changes: 2 additions & 0 deletions front/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import BrowserDetect from "./BrowserDetect";
import ErrorBoundary from "./ErrorBoundary";
import { FeatureFlagsProvider } from "./common/contexts/FeatureFlagsContext";
import { PermissionsProvider } from "./common/contexts/PermissionsContext";
import A11ySkipLinks from "./Apps/common/Components/A11ySkipLinks/A11ySkipLinks";

// Defines app-wide french error messages for yup
// See https://github.com/jquense/yup#using-a-custom-locale-dictionary
Expand All @@ -22,6 +23,7 @@ export default function App() {
<PermissionsProvider defaultPermissions={[]}>
<FeatureFlagsProvider defaultFeatureFlags={{}}>
<div className="App">
<A11ySkipLinks />
<LayoutContainer />
</div>
</FeatureFlagsProvider>
Expand Down
2 changes: 1 addition & 1 deletion front/src/Apps/Account/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default function Account() {
return (
<div id="account" className="account dashboard">
{!isMobile && <AccountMenu />}
<div className="dashboard-content">
<div id="account-info" className="dashboard-content" tabIndex={-1}>
<Routes>
<Route index element={<Redirect path={routes.account.info} />} />

Expand Down
2 changes: 1 addition & 1 deletion front/src/Apps/Companies/CompaniesList/CompaniesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export default function CompaniesList() {
additional={
<>
<Link className="fr-btn fr-mr-1w" to={routes.companies.orientation}>
Créer un établissement
<span id="create-company-link">Créer un établissement</span>
</Link>
<DropdownMenu
menuTitle="Exporter la liste"
Expand Down
16 changes: 9 additions & 7 deletions front/src/Apps/Companies/CompanyDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,15 @@ export default function CompanyDetails() {
</>
}
>
<Tabs
selectedTabId={selectedTabId}
tabs={tabs}
onTabChange={setSelectedTabId}
>
<CurrenComponent company={company} />
</Tabs>
<div id="company-tab-content" tabIndex={-1}>
<Tabs
selectedTabId={selectedTabId}
tabs={tabs}
onTabChange={setSelectedTabId}
>
<CurrenComponent company={company} />
</Tabs>
</div>
</AccountContentWrapper>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ const DashboardTabs = ({ currentCompany, companies }: DashboardTabsProps) => {

return (
<div className="dashboard-tabs">
<div className="company-select">
<div id="company-dashboard-select" className="company-select">
<CompanySwitcher
currentOrgId={currentCompany.orgId}
companies={companies}
Expand Down
171 changes: 171 additions & 0 deletions front/src/Apps/common/Components/A11ySkipLinks/A11ySkipLinks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import { MEDIA_QUERIES } from "../../../../common/config";
import { useMedia } from "../../../../common/use-media";
import routes from "../../../routes";
import React, { useRef } from "react";
import { matchPath, useLocation } from "react-router-dom";

const A11ySkipLinks = () => {
const location = useLocation();
const links = useRef<{ title; callback }[]>([]);
const isMobile = useMedia(`(max-width: ${MEDIA_QUERIES.handHeld})`);

const matchDashboard = matchPath(
{
path: routes.dashboard.index,
caseSensitive: false,
end: false
},
location.pathname
);

const matchCompanies = matchPath(
{
path: routes.companies.index,
caseSensitive: false,
end: true
},
location.pathname
);
const matchCompanyDetails = matchPath(
{
path: routes.companies.details,
caseSensitive: false,
end: false
},
location.pathname
);
const matchRegistry = matchPath(
{
path: routes.registry,
caseSensitive: false,
end: false
},
location.pathname
);
const matchAccount = matchPath(
{
path: routes.account.info,
caseSensitive: false,
end: false
},
location.pathname
);
const matchAdmin = matchPath(
{
path: routes.admin.verification,
caseSensitive: false,
end: false
},
location.pathname
);

const matchSignIn = matchPath(
{
path: routes.login,
caseSensitive: false,
end: false
},
location.pathname
);

const matchSignUp = matchPath(
{
path: routes.signup.index,
caseSensitive: false,
end: false
},
location.pathname
);
const matchPasswordResetRequest = matchPath(
{
path: routes.passwordResetRequest,
caseSensitive: false,
end: false
},
location.pathname
);

if (matchSignIn || matchSignUp || matchPasswordResetRequest) {
links.current = [
{
title: "Contenu",
callback: () => {
matchSignUp
? document.getElementById("fullnameSignUp")?.focus()
: document.getElementsByName("email")?.[0]?.focus();
}
}
];
} else {
links.current = [
{
title: "Menu principal",
callback: () => {
// @ts-ignore
document.getElementById("header-all-bsds-link")?.firstChild?.focus();
}
},
{
title: "Menu secondaire",
callback: () => {
if (matchDashboard) {
//dashboard company switcher
document
.getElementById("company-dashboard-select")
//@ts-ignore
?.firstChild?.firstChild?.focus();
} else {
//first accordion element
document
.getElementById("td-sidebar")
//@ts-ignore
?.firstChild?.firstChild?.firstChild?.focus();
}
}
},
{
title: "Contenu",
callback: () => {
if (matchDashboard) {
document.getElementById("create-bsd-btn")?.focus();
}
if (matchCompanies) {
// @ts-ignore
document.getElementById("create-company-link")?.parentNode?.focus();
}
if (matchCompanyDetails) {
document.getElementById("company-tab-content")?.focus();
}
if (matchRegistry) {
document.getElementsByName("exportType")?.[0]?.focus();
}
if (matchAccount) {
document.getElementById("account-info")?.focus();
}
if (matchAdmin) {
document.getElementById("admin-content")?.focus();
}
}
}
];
}
if (isMobile) return null;

return (
<div className="fr-skiplinks">
<nav className="fr-container" role="navigation" aria-label="Accès rapide">
<ul className="fr-skiplinks__list">
{links?.current?.map(link => (
<li key={link.title}>
<button className="fr-link" onClick={link.callback}>
{link.title}
</button>
</li>
))}
</ul>
</nav>
</div>
);
};

export default A11ySkipLinks;
15 changes: 13 additions & 2 deletions front/src/Apps/common/Components/DropdownMenu/DropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const DropdownMenu = ({
})}
>
<button
id="create-bsd-btn"
className={classNames(
`menu-btn fr-btn fr-btn--${primary ? "primary" : "secondary"}`,
{
Expand All @@ -46,6 +47,7 @@ const DropdownMenu = ({
)}
disabled={isDisabled}
onClick={toggleMenu}
aria-label={isOpen ? `Fermer ${menuTitle}` : `Ouvrir ${menuTitle}`}
>
{menuTitle}
</button>
Expand All @@ -71,10 +73,14 @@ const DropdownMenu = ({
}}
>
{link.icon && (
<span className="dropdown-menu__content__icon">
<span
className="dropdown-menu__content__icon"
aria-hidden
>
{link.icon}
</span>
)}
<span className="sr-only">{menuTitle}</span>
{link.title}
</button>
) : (
Expand All @@ -88,15 +94,20 @@ const DropdownMenu = ({
state={link.state && { ...link.state }}
>
{link.icon && (
<span className="dropdown-menu__content__icon">
<span
className="dropdown-menu__content__icon"
aria-hidden
>
{link.icon}
</span>
)}
{link.iconId && (
<span
aria-hidden
className={classNames([iconId, "fr-btn--icon-left"])}
></span>
)}
<span className="fr-sr-only">{menuTitle}</span>
{link.title}
</Link>
)}
Expand Down
6 changes: 5 additions & 1 deletion front/src/Apps/common/Components/SideBar/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ interface SideBarProps {
}

const SideBar = ({ children }: SideBarProps) => {
return <aside className="sidebarv2">{children}</aside>;
return (
<aside id="td-sidebar" className="sidebarv2">
{children}
</aside>
);
};
export default React.memo(SideBar);
14 changes: 11 additions & 3 deletions front/src/Apps/common/Components/layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ function MobileSubNav({ currentCompany }) {
</div>
);
}
const allBsdsMenuEntryLbl = "Mes bordereaux";

const getDesktopMenuEntries = (
isAuthenticated,
Expand All @@ -448,10 +449,9 @@ const getDesktopMenuEntries = (
navlink: true
}
];

const connected = [
{
caption: "Mes bordereaux",
caption: allBsdsMenuEntryLbl,
href: currentSiret
? generatePath(routes.dashboard.index, {
siret: currentSiret
Expand Down Expand Up @@ -766,7 +766,15 @@ export default function Header({
style={{ margin: "initial", maxWidth: "initial" }}
>
{menuEntries.map((e, idx) => (
<li className="fr-nav__item" key={idx}>
<li
id={
e.caption === allBsdsMenuEntryLbl
? "header-all-bsds-link"
: ""
}
className="fr-nav__item"
key={idx}
>
<MenuLink entry={e} />
</li>
))}
Expand Down
6 changes: 5 additions & 1 deletion front/src/admin/Admin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,11 @@ export default function Admin() {
</Accordion>
</SideBar>

<div className="dashboard-content fr-p-4w">
<div
id="admin-content"
className="dashboard-content fr-p-4w"
tabIndex={-1}
>
<Routes>
<Route
path={toRelative(routes.admin.verification)}
Expand Down
3 changes: 2 additions & 1 deletion front/src/login/Signup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ export default function Signup() {
label="Nom et prénom"
nativeInputProps={{
required: true,
onChange: e => setNameValue(e.target.value)
onChange: e => setNameValue(e.target.value),
id: "fullnameSignUp"
}}
/>
<Input
Expand Down

0 comments on commit 926ff46

Please sign in to comment.