From f2458db07c394ee4d11802d8f7b519191518e423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kent=20Mossb=C3=A4ck?= Date: Tue, 31 Mar 2026 12:25:01 +0200 Subject: [PATCH 01/15] feat: add 'Skip to tool menu' functionality and translations for accessibility --- .../pxweb2/public/locales/ar/translation.json | 1 + .../pxweb2/public/locales/en/translation.json | 1 + .../pxweb2/public/locales/no/translation.json | 3 +- .../pxweb2/public/locales/sv/translation.json | 1 + packages/pxweb2/src/@types/resources.d.ts | 1 + .../components/SkipToMain/SkipToToolsMenu.tsx | 48 +++++++++++++++++++ .../src/app/pages/TableViewer/TableViewer.tsx | 9 +++- 7 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx diff --git a/packages/pxweb2/public/locales/ar/translation.json b/packages/pxweb2/public/locales/ar/translation.json index 0e70037cc..a8a02106d 100644 --- a/packages/pxweb2/public/locales/ar/translation.json +++ b/packages/pxweb2/public/locales/ar/translation.json @@ -24,6 +24,7 @@ } }, "skip_to_main": "انتقل إلى المحتوى الرئيسي", + "skip_to_toolsmenu": " انتقل إلى قائمة الأدوات", "switch_language_landmark": "اختر اللغة", "footer": { "language_header": "اللغة", diff --git a/packages/pxweb2/public/locales/en/translation.json b/packages/pxweb2/public/locales/en/translation.json index 1b41dbf32..6901fe09f 100644 --- a/packages/pxweb2/public/locales/en/translation.json +++ b/packages/pxweb2/public/locales/en/translation.json @@ -24,6 +24,7 @@ } }, "skip_to_main": "Skip to main content", + "skip_to_toolsmenu": "Skip to tool menu for table", "switch_language_landmark": "Select language", "footer": { "language_header": "Language", diff --git a/packages/pxweb2/public/locales/no/translation.json b/packages/pxweb2/public/locales/no/translation.json index ca38dc446..80677bb6e 100644 --- a/packages/pxweb2/public/locales/no/translation.json +++ b/packages/pxweb2/public/locales/no/translation.json @@ -23,7 +23,8 @@ "action_text": "Last siden på nytt" } }, - "skip_to_main": "Hopp til hovedinnhold", + "skip_to_main": "Gå til hovedinnhold", + "skip_to_toolsmenu": "Gå til verktøymeny for tabell", "switch_language_landmark": "Velg språk", "footer": { "language_header": "Språk", diff --git a/packages/pxweb2/public/locales/sv/translation.json b/packages/pxweb2/public/locales/sv/translation.json index 539303aea..933e4682b 100644 --- a/packages/pxweb2/public/locales/sv/translation.json +++ b/packages/pxweb2/public/locales/sv/translation.json @@ -24,6 +24,7 @@ } }, "skip_to_main": "Gå direkt till huvudinnehållet", + "skip_to_toolsmenu": "Gå direkt till verktygsmeny för tabell", "switch_language_landmark": "Välj språk", "footer": { "language_header": "Språk", diff --git a/packages/pxweb2/src/@types/resources.d.ts b/packages/pxweb2/src/@types/resources.d.ts index 2976812fe..1ce7f0171 100644 --- a/packages/pxweb2/src/@types/resources.d.ts +++ b/packages/pxweb2/src/@types/resources.d.ts @@ -58,6 +58,7 @@ interface Resources { logo_alt: 'To the front page'; }; skip_to_main: 'Skip to main content'; + skip_to_toolsmenu: 'Skip to tool menu for table'; status_messages: { drawer_edit: 'More tools for editing the table are under construction.'; drawer_help: 'The help section is under construction. It will be possible to set up links that point directly to your own help pages.'; diff --git a/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx b/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx new file mode 100644 index 000000000..ef0d0d475 --- /dev/null +++ b/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import cl from 'clsx'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useSearchParams } from 'react-router'; + +import classes from './SkipToMain.module.scss'; +import { Link } from '@pxweb2/pxweb2-ui'; +import { getConfig } from '../../util/config/getConfig'; +import { getLanguagePath } from '../../util/language/getLanguagePath'; + +export const SkipToToolsMenu = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>((props, ref) => { + const { t, i18n } = useTranslation(); + const config = getConfig(); + const location = useLocation().pathname; + const [searchParams] = useSearchParams(); + + const basePath = getLanguagePath( + location, + i18n.language, + config.language.supportedLanguages, + config.language.defaultLanguage, + config.language.showDefaultLanguageInPath, + config.baseApplicationPath, + config.language.positionInPath, + ); + + // build a single, URL-encoded query string from the search params + const paramsString = searchParams.toString(); // URLSearchParams handles encoding + const params = paramsString ? `?${paramsString}` : ''; + const path = `${basePath}${params}#px-table-viewer-outer-container`; + + return ( +
+ + {t('common.skip_to_toolsmenu')} + +
+ ); +}); + +SkipToToolsMenu.displayName = 'SkipToToolsMenu'; \ No newline at end of file diff --git a/packages/pxweb2/src/app/pages/TableViewer/TableViewer.tsx b/packages/pxweb2/src/app/pages/TableViewer/TableViewer.tsx index 9be60f944..23687a308 100644 --- a/packages/pxweb2/src/app/pages/TableViewer/TableViewer.tsx +++ b/packages/pxweb2/src/app/pages/TableViewer/TableViewer.tsx @@ -10,6 +10,7 @@ import { NavigationItem } from '../../components/NavigationMenu/NavigationItem/N import NavigationRail from '../../components/NavigationMenu/NavigationRail/NavigationRail'; import NavigationBar from '../../components/NavigationMenu/NavigationBar/NavigationBar'; import { SkipToMain } from '../../components/SkipToMain/SkipToMain'; +import { SkipToToolsMenu } from '../../components/SkipToMain/SkipToToolsMenu'; import { Footer } from '../../components/Footer/Footer'; import useAccessibility from '../../context/useAccessibility'; import useApp from '../../context/useApp'; @@ -173,13 +174,17 @@ export function TableViewer() { }; const isSmallScreen = isTablet === true || isMobile === true; - return ( <> - +
+ + +
+ {!isSmallScreen &&
} {/* tabindex={-1} to fix firefox focusing this div*/}
Date: Tue, 31 Mar 2026 12:26:45 +0200 Subject: [PATCH 02/15] fix: ensure newline at end of file in SkipToToolsMenu component --- .../pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx b/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx index ef0d0d475..231e7921d 100644 --- a/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx +++ b/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx @@ -45,4 +45,4 @@ export const SkipToToolsMenu = React.forwardRef< ); }); -SkipToToolsMenu.displayName = 'SkipToToolsMenu'; \ No newline at end of file +SkipToToolsMenu.displayName = 'SkipToToolsMenu'; From 8b929f5d61953170249e551399974d353d06b5a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kent=20Mossb=C3=A4ck?= Date: Tue, 31 Mar 2026 13:03:58 +0200 Subject: [PATCH 03/15] feat: refactor SkipToMain and SkipToToolsMenu components to use SkipLink for improved code reuse --- .../app/components/SkipToMain/SkipLink.tsx | 54 +++++++++++++++++++ .../app/components/SkipToMain/SkipToMain.tsx | 40 ++------------ .../components/SkipToMain/SkipToToolsMenu.tsx | 51 ++++-------------- 3 files changed, 70 insertions(+), 75 deletions(-) create mode 100644 packages/pxweb2/src/app/components/SkipToMain/SkipLink.tsx diff --git a/packages/pxweb2/src/app/components/SkipToMain/SkipLink.tsx b/packages/pxweb2/src/app/components/SkipToMain/SkipLink.tsx new file mode 100644 index 000000000..a66e55ba0 --- /dev/null +++ b/packages/pxweb2/src/app/components/SkipToMain/SkipLink.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import cl from 'clsx'; +import { useTranslation } from 'react-i18next'; +import { useLocation, useSearchParams } from 'react-router'; + +import classes from './SkipToMain.module.scss'; +import { Link } from '@pxweb2/pxweb2-ui'; +import { getConfig } from '../../util/config/getConfig'; +import { getLanguagePath } from '../../util/language/getLanguagePath'; + +type SkipTranslationKey = 'common.skip_to_main' | 'common.skip_to_toolsmenu'; + +export type SkipLinkProps = React.HTMLAttributes & { + targetId: string; + translationKey: SkipTranslationKey; +}; + +export const SkipLink = React.forwardRef( + ({ targetId, translationKey, ...props }, ref) => { + const { t, i18n } = useTranslation(); + const config = getConfig(); + const location = useLocation().pathname; + const [searchParams] = useSearchParams(); + + const basePath = getLanguagePath( + location, + i18n.language, + config.language.supportedLanguages, + config.language.defaultLanguage, + config.language.showDefaultLanguageInPath, + config.baseApplicationPath, + config.language.positionInPath, + ); + + // Build a single, URL-encoded query string from the search params. + const paramsString = searchParams.toString(); + const params = paramsString ? `?${paramsString}` : ''; + const path = `${basePath}${params}#${targetId}`; + + return ( +
+ + {t(translationKey)} + +
+ ); + }, +); + +SkipLink.displayName = 'SkipLink'; diff --git a/packages/pxweb2/src/app/components/SkipToMain/SkipToMain.tsx b/packages/pxweb2/src/app/components/SkipToMain/SkipToMain.tsx index bdb66f42d..6a33b8ce2 100644 --- a/packages/pxweb2/src/app/components/SkipToMain/SkipToMain.tsx +++ b/packages/pxweb2/src/app/components/SkipToMain/SkipToMain.tsx @@ -1,47 +1,17 @@ import React from 'react'; -import cl from 'clsx'; -import { useTranslation } from 'react-i18next'; -import { useLocation, useSearchParams } from 'react-router'; - -import classes from './SkipToMain.module.scss'; -import { Link } from '@pxweb2/pxweb2-ui'; -import { getConfig } from '../../util/config/getConfig'; -import { getLanguagePath } from '../../util/language/getLanguagePath'; +import { SkipLink } from './SkipLink'; export const SkipToMain = React.forwardRef< HTMLDivElement, React.HTMLAttributes >((props, ref) => { - const { t, i18n } = useTranslation(); - const config = getConfig(); - const location = useLocation().pathname; - const [searchParams] = useSearchParams(); - - const basePath = getLanguagePath( - location, - i18n.language, - config.language.supportedLanguages, - config.language.defaultLanguage, - config.language.showDefaultLanguageInPath, - config.baseApplicationPath, - config.language.positionInPath, - ); - - // build a single, URL-encoded query string from the search params - const paramsString = searchParams.toString(); // URLSearchParams handles encoding - const params = paramsString ? `?${paramsString}` : ''; - const path = `${basePath}${params}#px-main-content`; - return ( -
- - {t('common.skip_to_main')} - -
+ /> ); }); diff --git a/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx b/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx index 231e7921d..8d3739444 100644 --- a/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx +++ b/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx @@ -1,48 +1,19 @@ import React from 'react'; -import cl from 'clsx'; -import { useTranslation } from 'react-i18next'; -import { useLocation, useSearchParams } from 'react-router'; -import classes from './SkipToMain.module.scss'; -import { Link } from '@pxweb2/pxweb2-ui'; -import { getConfig } from '../../util/config/getConfig'; -import { getLanguagePath } from '../../util/language/getLanguagePath'; +import { SkipLink } from './SkipLink'; export const SkipToToolsMenu = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes + HTMLDivElement, + React.HTMLAttributes >((props, ref) => { - const { t, i18n } = useTranslation(); - const config = getConfig(); - const location = useLocation().pathname; - const [searchParams] = useSearchParams(); - - const basePath = getLanguagePath( - location, - i18n.language, - config.language.supportedLanguages, - config.language.defaultLanguage, - config.language.showDefaultLanguageInPath, - config.baseApplicationPath, - config.language.positionInPath, - ); - - // build a single, URL-encoded query string from the search params - const paramsString = searchParams.toString(); // URLSearchParams handles encoding - const params = paramsString ? `?${paramsString}` : ''; - const path = `${basePath}${params}#px-table-viewer-outer-container`; - - return ( -
- - {t('common.skip_to_toolsmenu')} - -
- ); + return ( + + ); }); SkipToToolsMenu.displayName = 'SkipToToolsMenu'; From 319706ec5fed884e8fb7b213cbaa1319d14c5883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kent=20Mossb=C3=A4ck?= Date: Tue, 31 Mar 2026 13:04:45 +0200 Subject: [PATCH 04/15] style: format SkipToToolsMenu component for improved readability --- .../components/SkipToMain/SkipToToolsMenu.tsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx b/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx index 8d3739444..19e58542f 100644 --- a/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx +++ b/packages/pxweb2/src/app/components/SkipToMain/SkipToToolsMenu.tsx @@ -3,17 +3,17 @@ import React from 'react'; import { SkipLink } from './SkipLink'; export const SkipToToolsMenu = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes + HTMLDivElement, + React.HTMLAttributes >((props, ref) => { - return ( - - ); + return ( + + ); }); SkipToToolsMenu.displayName = 'SkipToToolsMenu'; From 895906c73dfd2d55f1f4d92e1a59e5e9ff353d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kent=20Mossb=C3=A4ck?= Date: Mon, 20 Apr 2026 15:22:02 +0200 Subject: [PATCH 05/15] fix: adjust margin for focus state in SkipToMain component --- .../pxweb2/src/app/components/SkipToMain/SkipToMain.module.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/pxweb2/src/app/components/SkipToMain/SkipToMain.module.scss b/packages/pxweb2/src/app/components/SkipToMain/SkipToMain.module.scss index 087bf7b6c..e787166d7 100644 --- a/packages/pxweb2/src/app/components/SkipToMain/SkipToMain.module.scss +++ b/packages/pxweb2/src/app/components/SkipToMain/SkipToMain.module.scss @@ -5,6 +5,7 @@ width: 100%; height: 48px; justify-content: center; + margin: -1px; } } From 2860f22bf0af7871e337ab809e5194c345c923d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kent=20Mossb=C3=A4ck?= Date: Wed, 22 Apr 2026 13:49:07 +0200 Subject: [PATCH 06/15] fix: add aria-hidden attribute to header for accessibility --- packages/pxweb2/src/app/components/Header/Header.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pxweb2/src/app/components/Header/Header.tsx b/packages/pxweb2/src/app/components/Header/Header.tsx index 9dc1ee382..b024bb41f 100644 --- a/packages/pxweb2/src/app/components/Header/Header.tsx +++ b/packages/pxweb2/src/app/components/Header/Header.tsx @@ -40,7 +40,7 @@ export const Header = ({ stroke = false }: HeaderProps) => { const logoUrl = homePageUrl || defaultPath; return ( -
+