diff --git a/components/header/header-core/index.tsx b/components/header/header-core/index.tsx index 15602f806..742a1ae61 100644 --- a/components/header/header-core/index.tsx +++ b/components/header/header-core/index.tsx @@ -30,99 +30,101 @@ export const HeaderCore: React.FC = ({ pathFrom, }) => { return ( -
+ <> - +
+ - -
-
-
-
-
-
- - {useSearchBar || useLogo ? ( -
- - - - - + + +
+
+
+
+ - {useSearchBar ? ( -
- -
- ) : null} -
-
-
-
    -
  • + {useSearchBar || useLogo ? ( + + ) : null} +
    -
  • -
+
+
+ {useSearchBar ? ( +
+ +
+ ) : null} +
+
+
+
    +
  • + +
  • +
+
-
- {plugin} - - -
+ {plugin} + + +
+ ); }; diff --git a/components/load-bar/index.tsx b/components/load-bar/index.tsx index eccc79e8b..1fbc0b235 100644 --- a/components/load-bar/index.tsx +++ b/components/load-bar/index.tsx @@ -4,27 +4,27 @@ import { useEffect } from 'react'; import constants from '#models/constants'; import { EScope, hasRights } from '#models/user/rights'; import { ISession } from '#models/user/session'; - +import styles from './style.module.css'; export default function LoadBar({ session }: { session: ISession | null }) { useEffect(() => { const loadBar = loadBarFactory(); if (typeof window !== 'undefined') { - window.addEventListener('beforeunload', loadBar.run); + window.addEventListener( + 'beforeunload', + loadBar.runWithDelay.bind(loadBar) + ); + window.addEventListener('runloadbar', loadBar.runImmediate.bind(loadBar)); + window.addEventListener('cancelloadbar', loadBar.cancel.bind(loadBar)); } }, []); return (
); @@ -71,8 +71,7 @@ const loadBarFactory = () => { return { _currentJobId: '', _loader: null as HTMLElement | null, - - run: async function () { + async _run(step: number) { const jobId = Math.random().toString(16).substring(7); this._currentJobId = jobId; @@ -84,14 +83,29 @@ const loadBarFactory = () => { return; } } - - for (let w of positions) { + this._loader.style.opacity = '1'; + for (let i = step; i < positions.length; i++) { // interrupt job if another job has been triggered by another beforeunload event if (this._currentJobId !== jobId) { return; } - this._loader.style.width = `${w}vw`; + this._loader.style.width = `${positions[i]}%`; + await wait(200); + } + }, + runImmediate() { + this._run(2); + }, + runWithDelay() { + this._run(0); + }, + async cancel() { + this._currentJobId = ''; + if (this._loader) { + this._loader.style.width = '100%'; + this._loader.style.opacity = '0'; await wait(200); + this._loader.style.width = '0'; } }, }; diff --git a/components/load-bar/style.module.css b/components/load-bar/style.module.css new file mode 100644 index 000000000..00f8fe94d --- /dev/null +++ b/components/load-bar/style.module.css @@ -0,0 +1,9 @@ +.load-bar { + transition: all 200ms ease-in-out; + height: 3px; + width: 0; + opacity: 0; + position: fixed; + top: 0; + z-index: 9999; +} diff --git a/components/title-section/tabs/index.tsx b/components/title-section/tabs/index.tsx index 1e648ddfe..d6c5af760 100644 --- a/components/title-section/tabs/index.tsx +++ b/components/title-section/tabs/index.tsx @@ -1,3 +1,4 @@ +import Link from 'next/link'; import { PrintNever } from '#components-ui/print-visibility'; import { checkHasLabelsAndCertificates, @@ -11,6 +12,7 @@ import { import { EScope, hasRights } from '#models/user/rights'; import { ISession } from '#models/user/session'; import styles from './styles.module.css'; +import TabLink from './tab-link'; export enum FICHE { INFORMATION = 'résumé', @@ -135,30 +137,27 @@ export const Tabs: React.FC<{ noFollow, width = 'auto', }) => ( - - {currentFicheType === ficheType ? label :

{label}

} -
+ width={width} + /> ) )} {currentFicheType === FICHE.ETABLISSEMENT && ( <>
-

Fiche établissement

-
+ )}
diff --git a/components/title-section/tabs/styles.module.css b/components/title-section/tabs/styles.module.css index 65c81c7bb..f338691c1 100644 --- a/components/title-section/tabs/styles.module.css +++ b/components/title-section/tabs/styles.module.css @@ -56,6 +56,7 @@ } } -.titleTabs > a:hover { +.titleTabs > a:hover, +.titleTabs > a:focus { background-color: var(--annuaire-colors-pastelBlue); } diff --git a/components/title-section/tabs/tab-link.tsx b/components/title-section/tabs/tab-link.tsx new file mode 100644 index 000000000..b5441bc4a --- /dev/null +++ b/components/title-section/tabs/tab-link.tsx @@ -0,0 +1,39 @@ +'use client'; + +import Link from 'next/link'; +import { useEffect } from 'react'; +import styles from './styles.module.css'; +type IProps = { + label: string; + href: string; + noFollow?: boolean; + width?: string; + active: boolean; +}; +export default function TabLink({ + active, + href, + label, + noFollow, + width, +}: IProps) { + useEffect(() => { + active === false && window.dispatchEvent(new Event('cancelloadbar')); + }, [active]); + useEffect(() => { + window.dispatchEvent(new Event('cancelloadbar')); + }, []); + return ( + window.dispatchEvent(new Event('runloadbar'))} + prefetch={false} + > + {active ? label :

{label}

} + + ); +}