From 2ff385a4b6b0f7bfb653995c5aa76e18f99f5575 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Thu, 6 Feb 2025 10:21:56 +0100 Subject: [PATCH] fix(1-3295): fix broken skip link (#9239) Fixes the issue where the skip link wouldn't take you to the main content of the page anymore. Also includes a few related minor semantic and a11y improvements: 1. The `main` element now only surrounds the actual main content of the page. The sidebar is nav content and shouldn't be within it. The easiest way to do this was to change the element that was previously a `main` to a `div` and make the main content wrapper a `main` instead. 2. Makes the skip link target visible when focused. But invisible otherwise. This has two benefits: 1. It's immediately obvious that using the skip link has worked. It tells you that it's at the start of the main content. 2. Because the link now has text, it can be targeted by link search (e.g. in Firefox, press `'` to search for links (I use this **a lot**)), making it super easy to move your focus to the main content directly. (Yes, landmark navigation should also work here, though, especially with the `main` change). The implementation of UI considerations of the skip link are based on the CSS-tricks article [a deep dive on skipping to content](https://css-tricks.com/a-deep-dive-on-skipping-to-content/) from 2021. Here's what it looks like when you skip to content: ![image](https://github.com/user-attachments/assets/c22819e6-f801-47d8-a9d9-908c250fd6ba) When it doesn't have focus, it's invisible. --- .../common/SkipNavLink/SkipNavTarget.tsx | 35 ++++++++++++++++++- .../layout/MainLayout/MainLayout.tsx | 6 ++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/frontend/src/component/common/SkipNavLink/SkipNavTarget.tsx b/frontend/src/component/common/SkipNavLink/SkipNavTarget.tsx index feeff614fe..c5882ffa38 100644 --- a/frontend/src/component/common/SkipNavLink/SkipNavTarget.tsx +++ b/frontend/src/component/common/SkipNavLink/SkipNavTarget.tsx @@ -1,5 +1,38 @@ +import { styled } from '@mui/material'; + export const SKIP_NAV_TARGET_ID = 'skip-nav-target-id'; +const SkipLinkTarget = styled('a')(({ theme }) => ({ + clipPath: 'polygon(0 0, 0 0, 0 0, 0 0)', + boxSizing: 'border-box', + position: 'absolute', + margin: 0, + padding: 0, + + top: 0, + left: 0, + width: '100%', + + ':focus': { + clipPath: 'none', + zIndex: 999, + height: '80px', + lineHeight: '80px', + fontSize: theme.typography.body1.fontSize, + textDecoration: 'none', + textAlign: 'center', + + background: theme.palette.primary.main, + color: theme.palette.primary.contrastText, + + outline: 'none', + }, +})); + export const SkipNavTarget = () => { - return
; + return ( + + Start of main content + + ); }; diff --git a/frontend/src/component/layout/MainLayout/MainLayout.tsx b/frontend/src/component/layout/MainLayout/MainLayout.tsx index f37789d0a9..f743bdc40d 100644 --- a/frontend/src/component/layout/MainLayout/MainLayout.tsx +++ b/frontend/src/component/layout/MainLayout/MainLayout.tsx @@ -33,7 +33,7 @@ const MainLayoutContainer = styled(Grid)(() => ({ position: 'relative', })); -const MainLayoutContentWrapper = styled('main')(({ theme }) => ({ +const MainLayoutContentWrapper = styled('div')(({ theme }) => ({ margin: theme.spacing(0, 'auto'), flexGrow: 1, width: '100%', @@ -80,7 +80,7 @@ const StyledImg = styled('img')(() => ({ userSelect: 'none', })); -const MainLayoutContentContainer = styled('div')(({ theme }) => ({ +const MainLayoutContentContainer = styled('main')(({ theme }) => ({ height: '100%', padding: theme.spacing(0, 0, 6.5, 0), position: 'relative', @@ -110,7 +110,6 @@ export const MainLayout = forwardRef( show={
} /> - ( +