Skip to content

Commit

Permalink
feat(US-209): WIP ajoute lien évitement
Browse files Browse the repository at this point in the history
  • Loading branch information
elba-octo committed Nov 28, 2023
1 parent bca400e commit 099cc05
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 7 deletions.
70 changes: 63 additions & 7 deletions components/layouts/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@

import { apm } from '@elastic/apm-rum'
import dynamic from 'next/dynamic'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useTheme } from 'next-themes'
import React, { ReactElement, useEffect, useRef, useState } from 'react'
import React, {
forwardRef,
ReactElement,
Ref,
useEffect,
useImperativeHandle,
useRef,
useState,
} from 'react'

import AppHead from 'components/AppHead'
import { MODAL_ROOT_ID } from 'components/Modal'
Expand Down Expand Up @@ -54,12 +63,29 @@ export default function Layout({ children }: LayoutProps) {

const containerRef = useRef<HTMLDivElement>(null)
const mainRef = useRef<HTMLDivElement>(null)
const skipLinkRefContainer = useRef<HTMLSpanElement>(null)
const mainRefContainer = useRef<HTMLDivElement>(null)
const [hasMessageNonLu, setHasMessageNonLu] = useState(false)

const pageCouranteEstMessagerie = router.pathname === '/messagerie'

const withChat = !withoutChat

function focusOnMain() {
const findFirstFocusableElement = (element) => {
const focusableElements = element.querySelectorAll(
'button, a[href], input, select, textarea, [tabindex]:not([tabindex="-1"], [role="tablist"])'
)
return focusableElements[0]
}
if (mainRef.current) {
const firstFocusableElement = findFirstFocusableElement(mainRef.current)
if (firstFocusableElement) {
firstFocusableElement.focus()
}
}
}

useEffect(() => {
// https://dev.to/admitkard/mobile-issue-with-100vh-height-100-100vh-3-solutions-3nae
function resizeContainerToInnerHeight() {
Expand All @@ -75,10 +101,6 @@ export default function Layout({ children }: LayoutProps) {
window.removeEventListener('resize', resizeContainerToInnerHeight, true)
}, [])

useEffect(() => {
if (mainRef.current) mainRef.current.scrollTo(0, 0)
}, [router.asPath, mainRef])

useEffect(() => {
if (!conseiller) {
Promise.all([
Expand Down Expand Up @@ -116,9 +138,16 @@ export default function Layout({ children }: LayoutProps) {
}
}, [conseiller, conseiller?.structure, setTheme])

useEffect(() => {
if (skipLinkRefContainer.current) {
skipLinkRefContainer.current.focus()
}
}, [skipLinkRefContainer, router.pathname])

return (
<>
<AppHead hasMessageNonLu={hasMessageNonLu} titre={pageTitle} />
<LienEvitement ref={skipLinkRefContainer} onClick={focusOnMain} />

{!conseiller && <SpinningLoader />}

Expand All @@ -134,7 +163,7 @@ export default function Layout({ children }: LayoutProps) {
<SidebarLayout />

<div
ref={mainRef}
ref={mainRefContainer}
className={`${styles.page} ${
withChat ? styles.page_when_chat : ''
}`}
Expand All @@ -146,7 +175,9 @@ export default function Layout({ children }: LayoutProps) {
/>

<main
ref={mainRef}
role='main'
id='contenu'
className={`${styles.content} ${
withChat ? styles.content_when_chat : ''
}`}
Expand Down Expand Up @@ -178,8 +209,10 @@ export default function Layout({ children }: LayoutProps) {
pageEstMessagerie={true}
/>

<div ref={mainRef} className={styles.page}>
<div ref={mainRefContainer} className={styles.page}>
<main
ref={mainRef}
id='contenu'
role='main'
className={`${styles.content} ${styles.messagerie_full_screen}`}
>
Expand All @@ -197,3 +230,26 @@ export default function Layout({ children }: LayoutProps) {
</>
)
}

const LienEvitement = forwardRef(
(props: { onClick: () => void }, forwardedRef: Ref<HTMLSpanElement>) => {
const { onClick } = props
const ref = useRef<HTMLSpanElement>(null)

useImperativeHandle(forwardedRef, () => ref.current as HTMLSpanElement)

return (
<span ref={ref} tabindex={-1}>
<Link
href='#contenu'
onClick={onClick}
className='sr-only focus:not-sr-only focus:text-primary'
>
Aller au contenu
</Link>
</span>
)
}
)

LienEvitement.displayName = 'LienEvitement'
8 changes: 8 additions & 0 deletions tests/components/Layout.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ describe('<Layout />', () => {
})
})

it("affiche le lien d'évitement", () => {
// Then
expect(
screen.getByRole('link', { name: 'Aller au contenu' })
).toHaveAttribute('href', '#contenu')
})

it('affiche le titre de la page', () => {
// Then
expect(
Expand All @@ -118,6 +125,7 @@ describe('<Layout />', () => {

it('contient la région (landmark) main', () => {
expect(screen.getByRole('main')).toBeInTheDocument()
expect(screen.getByRole('main')).toHaveAttribute('id', 'contenu')
})

it("affiche le fil d'ariane", () => {
Expand Down

0 comments on commit 099cc05

Please sign in to comment.