diff --git a/.vscode/settings.json b/.vscode/settings.json
index 24cb38a19a..03a41077b2 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -3,5 +3,11 @@
"^@mui/[^/]+$",
"(?=^|[^/])shared/((?!api)|api/(?!endpoints/testing)).+"
],
- "codescene.enableTelemetry": false
+ "codescene.enableTelemetry": false,
+ "jest.virtualFolders": [
+ { "name": "web", "rootPath": "web" },
+ { "name": "native", "rootPath": "native" },
+ { "name": "shared", "rootPath": "shared" },
+ { "name": "translations", "rootPath": "translations" }
+ ]
}
diff --git a/translations/translations.json b/translations/translations.json
index 2162650f26..774b8ff8fe 100644
--- a/translations/translations.json
+++ b/translations/translations.json
@@ -7738,7 +7738,8 @@
"skipToContent": "Zum Inhalt springen",
"shareQrCodeTitle": "Über QR-Code teilen",
"shareQrCodeDescription": "Teile diese Seite einfach, indem du den QR-Code auf einem anderen Gerät scannst.",
- "qrCode": "QR-Code"
+ "qrCode": "QR-Code",
+ "backToContent": "Zurück zum Inhalt"
},
"am": {
"imprint": "ዕትም",
@@ -8053,7 +8054,8 @@
"skipToContent": "Skip to content",
"shareQrCodeTitle": "Share via QR code",
"shareQrCodeDescription": "Share this page easily by scanning the QR code on another device.",
- "qrCode": "QR code"
+ "qrCode": "QR code",
+ "backToContent": "Back to content"
},
"es": {
"imprint": "Aviso legal",
diff --git a/web/src/components/BackToRegionButton.tsx b/web/src/components/BackToRegionButton.tsx
new file mode 100644
index 0000000000..73dd97c1cd
--- /dev/null
+++ b/web/src/components/BackToRegionButton.tsx
@@ -0,0 +1,38 @@
+import Button from '@mui/material/Button'
+import { styled } from '@mui/material/styles'
+import React, { ReactElement, useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import { useNavigate } from 'react-router'
+
+import useDimensions from '../hooks/useDimensions'
+import { DirectionDependentBackIcon } from './base/Dialog'
+
+const StyledButton = styled(Button)({
+ textTransform: 'none',
+ alignSelf: 'flex-start',
+})
+
+const BackToRegionButton = (): ReactElement | null => {
+ const navigate = useNavigate()
+ const { mobile } = useDimensions()
+ const { t } = useTranslation('layout')
+ const currentHistoryIndex = window.history.state?.idx ?? 0
+
+ // Initial history index to account for language changes or other user interactions on this page.
+ const [initialHistoryIndex] = useState(currentHistoryIndex)
+
+ if (!mobile || initialHistoryIndex === 0) {
+ return null
+ }
+
+ return (
+ navigate(initialHistoryIndex - currentHistoryIndex - 1)}
+ startIcon={}
+ color='inherit'>
+ {t('backToContent')}
+
+ )
+}
+
+export default BackToRegionButton
diff --git a/web/src/components/__tests__/BackToRegionButton.spec.tsx b/web/src/components/__tests__/BackToRegionButton.spec.tsx
new file mode 100644
index 0000000000..a7fa857b84
--- /dev/null
+++ b/web/src/components/__tests__/BackToRegionButton.spec.tsx
@@ -0,0 +1,42 @@
+import { fireEvent } from '@testing-library/react'
+import React from 'react'
+
+import { mockDimensions } from '../../__mocks__/useDimensions'
+import useDimensions from '../../hooks/useDimensions'
+import { renderWithRouterAndTheme } from '../../testing/render'
+import BackToRegionButton from '../BackToRegionButton'
+
+const mockNavigate = jest.fn()
+jest.mock('react-i18next')
+jest.mock('../../hooks/useDimensions')
+jest.mock('react-router', () => ({
+ ...jest.requireActual('react-router'),
+ useNavigate: () => mockNavigate,
+}))
+
+describe('BackToRegionButton', () => {
+ const { mocked } = jest
+
+ const setHistoryIndex = (idx: number) => window.history.replaceState({ idx }, '')
+
+ beforeEach(() => {
+ jest.clearAllMocks()
+ mocked(useDimensions).mockImplementation(() => ({ ...mockDimensions, mobile: true }))
+ setHistoryIndex(1)
+ })
+
+ it('should render on mobile and navigate back on click', () => {
+ const { getByText } = renderWithRouterAndTheme()
+
+ fireEvent.click(getByText('layout:backToContent'))
+
+ expect(mockNavigate).toHaveBeenCalledWith(-1)
+ })
+
+ it('should render nothing when there is no history to go back to', () => {
+ setHistoryIndex(0)
+ const { queryByText } = renderWithRouterAndTheme()
+
+ expect(queryByText('layout:backToContent')).toBeFalsy()
+ })
+})
diff --git a/web/src/routes/RegionsPage.tsx b/web/src/routes/RegionsPage.tsx
index 2fa8d5373d..0da124a325 100644
--- a/web/src/routes/RegionsPage.tsx
+++ b/web/src/routes/RegionsPage.tsx
@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next'
import { createRegionsEndpoint } from 'shared/api'
+import BackToRegionButton from '../components/BackToRegionButton'
import FailureSwitcherWithHelmet from '../components/FailureSwitcherWithHelmet'
import Footer from '../components/Footer'
import GeneralHeader from '../components/GeneralHeader'
@@ -44,6 +45,7 @@ const RegionsPage = ({ languageCode }: RegionsPageProps): ReactElement => {
>
}>
+
)