1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-15 01:16:22 +02:00

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.
This commit is contained in:
Thomas Heartman 2025-02-06 10:21:56 +01:00 committed by GitHub
parent 483e6c8acf
commit 2ff385a4b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 37 additions and 4 deletions

View File

@ -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 <div id={SKIP_NAV_TARGET_ID} />;
return (
<SkipLinkTarget href={`#${SKIP_NAV_TARGET_ID}`} id={SKIP_NAV_TARGET_ID}>
Start of main content
</SkipLinkTarget>
);
};

View File

@ -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<HTMLDivElement, IMainLayoutProps>(
show={<Header />}
/>
<SkipNavTarget />
<MainLayoutContainer>
<MainLayoutContentWrapper>
<ConditionallyRender
@ -154,6 +153,7 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
<MainLayoutEventTimeline />
<MainLayoutContent>
<SkipNavTarget />
<MainLayoutContentContainer ref={ref}>
<BreadcrumbNav />
<Proclamation toast={uiConfig.toast} />