Skip to content

Commit 6ca8b4f

Browse files
authored
UU: set focus to hidden element above skiplink on navigation (#2219)
* focus new element over skiplink when pathame is changed * fix * refactor: remove base tag, simplify skiplink, extra effect for navigationFocus * remove dead code
1 parent 4075e5d commit 6ca8b4f

4 files changed

Lines changed: 45 additions & 8 deletions

File tree

backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/Views/Home/Index.cshtml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
<!DOCTYPE html>
77
<html lang="no">
88
<head>
9-
<base href="~/accessmanagement/ui/"/>
109
<meta charset="UTF-8">
1110
<meta http-equiv="X-UA-Compatible" content="IE=edge">
1211
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.srOnly {
2+
border: 0;
3+
clip: rect(0 0 0 0);
4+
height: 1px;
5+
overflow: hidden;
6+
padding: 0;
7+
position: absolute;
8+
white-space: nowrap;
9+
width: 1px;
10+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { useEffect, useRef, useState } from 'react';
2+
import { useLocation } from 'react-router';
3+
import classes from './NavigationFocus.module.css';
4+
5+
export const NavigationFocus = () => {
6+
const { pathname } = useLocation();
7+
const skipRef = useRef<HTMLDivElement | null>(null);
8+
const [title, setTitle] = useState('');
9+
10+
useEffect(() => {
11+
const rafId = requestAnimationFrame(() => {
12+
setTitle(document.title);
13+
});
14+
return () => cancelAnimationFrame(rafId);
15+
}, [pathname]);
16+
17+
useEffect(() => {
18+
if (title) {
19+
skipRef.current?.focus({ preventScroll: true });
20+
}
21+
}, [title]);
22+
23+
return (
24+
<div
25+
className={classes.srOnly}
26+
tabIndex={-1}
27+
ref={skipRef}
28+
>
29+
{title}
30+
</div>
31+
);
32+
};

src/features/amUI/common/PageLayoutWrapper/PageLayoutWrapper.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React from 'react';
22
import type { LanguageCode } from '@altinn/altinn-components';
33
import { Layout, RootProvider, Snackbar } from '@altinn/altinn-components';
4-
import { useLocation } from 'react-router';
54

65
import { useGetReporteeQuery } from '@/rtk/features/userInfoApi';
76

@@ -11,8 +10,8 @@ import { useFooter } from './useFooter';
1110
import { useHeader } from './useHeader';
1211

1312
import { useTranslation } from 'react-i18next';
14-
import { GeneralPath } from '@/routes/paths';
1513
import { useSidebarItems } from './useSidebarItems';
14+
import { NavigationFocus } from './NavigationFocus';
1615

1716
interface PageLayoutWrapperProps {
1817
openAccountMenu?: boolean;
@@ -31,7 +30,6 @@ export const PageLayoutWrapper = ({
3130
}: PageLayoutWrapperProps): React.ReactNode => {
3231
const { t } = useTranslation();
3332
const { data: reportee } = useGetReporteeQuery();
34-
const { pathname, search } = useLocation();
3533

3634
const { menuGroups } = useGlobalMenu();
3735

@@ -44,6 +42,7 @@ export const PageLayoutWrapper = ({
4442

4543
return (
4644
<RootProvider languageCode={languageCode as LanguageCode}>
45+
<NavigationFocus />
4746
<Layout
4847
color={reportee?.type ? getAccountType(reportee.type) : 'neutral'}
4948
theme='subtle'
@@ -55,10 +54,7 @@ export const PageLayoutWrapper = ({
5554
variant: escalateBannerSeverity ? 'alert' : undefined,
5655
}}
5756
skipLink={{
58-
href:
59-
pathname === '/'
60-
? `${GeneralPath.BasePath}${search}#main-content`
61-
: `${GeneralPath.BasePath}${pathname}${search}#main-content`,
57+
href: '#main-content',
6258
color: 'inherit',
6359
size: 'xs',
6460
children: t('common.skiplink'),

0 commit comments

Comments
 (0)