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

[tra-14929]Ajouter des liens d'évitement Menu principal / secondaire / contenu (Aller à) #3626

Merged
merged 1 commit into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading