diff options
| -rw-r--r-- | src/components/Breadcrumb/Breadcrumb.module.scss | 21 | ||||
| -rw-r--r-- | src/components/Breadcrumb/Breadcrumb.tsx | 53 | ||||
| -rw-r--r-- | src/components/Layouts/Layout.tsx | 14 | ||||
| -rw-r--r-- | src/pages/404.tsx | 8 | ||||
| -rw-r--r-- | src/pages/article/[slug].tsx | 9 | ||||
| -rw-r--r-- | src/pages/blog/index.tsx | 9 | ||||
| -rw-r--r-- | src/pages/contact.tsx | 9 | ||||
| -rw-r--r-- | src/pages/cv.tsx | 7 | ||||
| -rw-r--r-- | src/pages/mentions-legales.tsx | 7 | ||||
| -rw-r--r-- | src/pages/recherche/index.tsx | 9 | ||||
| -rw-r--r-- | src/pages/sujet/[slug].tsx | 9 | ||||
| -rw-r--r-- | src/pages/thematique/[slug].tsx | 9 |
12 files changed, 128 insertions, 36 deletions
diff --git a/src/components/Breadcrumb/Breadcrumb.module.scss b/src/components/Breadcrumb/Breadcrumb.module.scss new file mode 100644 index 0000000..bfba21f --- /dev/null +++ b/src/components/Breadcrumb/Breadcrumb.module.scss @@ -0,0 +1,21 @@ +@use "@styles/abstracts/placeholders"; + +.list { + @extend %reset-ordered-list; + + display: flex; + flex-flow: row wrap; + align-items: center; + gap: var(--spacing-2xs); + margin: 0 0 var(--spacing-md) 0; + font-size: var(--font-size-sm); +} + +.item { + &:not(:last-of-type) { + &::after { + content: ">"; + margin-left: var(--spacing-2xs); + } + } +} diff --git a/src/components/Breadcrumb/Breadcrumb.tsx b/src/components/Breadcrumb/Breadcrumb.tsx new file mode 100644 index 0000000..e090a4f --- /dev/null +++ b/src/components/Breadcrumb/Breadcrumb.tsx @@ -0,0 +1,53 @@ +import { t } from '@lingui/macro'; +import Link from 'next/link'; +import { useRouter } from 'next/router'; +import styles from './Breadcrumb.module.scss'; + +const Breadcrumb = ({ pageTitle }: { pageTitle: string }) => { + const router = useRouter(); + + const isHome = router.pathname === '/'; + const isBlog = router.pathname === '/blog'; + const isArticle = router.pathname.includes('/article/'); + const isThematic = router.pathname.includes('/thematique/'); + const isSubject = router.pathname.includes('/sujet/'); + + const getItems = () => { + return ( + <> + <li className={styles.item}> + <Link href="/"> + <a>{t`Home`}</a> + </Link> + </li> + {isBlog && <li className={styles.item}>{t`Blog`}</li>} + {(isArticle || isThematic || isSubject) && ( + <> + <li className={styles.item}> + <Link href="/blog"> + <a>{t`Blog`}</a> + </Link> + </li> + <li className={styles.item}>{pageTitle}</li> + </> + )} + {!isBlog && !isArticle && !isThematic && !isSubject && ( + <li className={styles.item}>{pageTitle}</li> + )} + </> + ); + }; + + return ( + <> + {!isHome && ( + <nav> + <span className="screen-reader-text">{t`You are here:`}</span> + <ol className={styles.list}>{getItems()}</ol> + </nav> + )} + </> + ); +}; + +export default Breadcrumb; diff --git a/src/components/Layouts/Layout.tsx b/src/components/Layouts/Layout.tsx index 7f8ab9d..8c5570f 100644 --- a/src/components/Layouts/Layout.tsx +++ b/src/components/Layouts/Layout.tsx @@ -1,7 +1,8 @@ -import { ReactNode } from 'react'; +import { ReactElement, ReactNode } from 'react'; import Footer from '@components/Footer/Footer'; import Header from '@components/Header/Header'; import Main from '@components/Main/Main'; +import Breadcrumb from '@components/Breadcrumb/Breadcrumb'; const Layout = ({ children, @@ -19,4 +20,15 @@ const Layout = ({ ); }; +export const getLayout = (page: ReactElement) => { + const pageTitle: string = page.props.breadcrumbTitle; + + return ( + <Layout> + <Breadcrumb pageTitle={pageTitle} /> + {page} + </Layout> + ); +}; + export default Layout; diff --git a/src/pages/404.tsx b/src/pages/404.tsx index 903a386..6b6fbf5 100644 --- a/src/pages/404.tsx +++ b/src/pages/404.tsx @@ -1,4 +1,4 @@ -import Layout from '@components/Layouts/Layout'; +import { getLayout } from '@components/Layouts/Layout'; import { seo } from '@config/seo'; import { t, Trans } from '@lingui/macro'; import { NextPageWithLayout } from '@ts/types/app'; @@ -6,7 +6,6 @@ import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticProps, GetStaticPropsContext } from 'next'; import Head from 'next/head'; import Link from 'next/link'; -import { ReactElement } from 'react'; const error404: NextPageWithLayout = () => { return ( @@ -32,7 +31,7 @@ const error404: NextPageWithLayout = () => { ); }; -error404.getLayout = (page: ReactElement) => <Layout>{page}</Layout>; +error404.getLayout = getLayout; export const getStaticProps: GetStaticProps = async ( context: GetStaticPropsContext @@ -42,8 +41,11 @@ export const getStaticProps: GetStaticProps = async ( process.env.NODE_ENV === 'production' ); + const breadcrumbTitle = t`Error`; + return { props: { + breadcrumbTitle, translation, }, }; diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx index bb11220..621b2e2 100644 --- a/src/pages/article/[slug].tsx +++ b/src/pages/article/[slug].tsx @@ -1,6 +1,6 @@ import CommentForm from '@components/CommentForm/CommentForm'; import CommentsList from '@components/CommentsList/CommentsList'; -import Layout from '@components/Layouts/Layout'; +import { getLayout } from '@components/Layouts/Layout'; import PostFooter from '@components/PostFooter/PostFooter'; import PostHeader from '@components/PostHeader/PostHeader'; import { t } from '@lingui/macro'; @@ -11,7 +11,6 @@ import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next'; import Head from 'next/head'; import { ParsedUrlQuery } from 'querystring'; -import { ReactElement } from 'react'; const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => { const { @@ -53,9 +52,7 @@ const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => { ); }; -SingleArticle.getLayout = function getLayout(page: ReactElement) { - return <Layout>{page}</Layout>; -}; +SingleArticle.getLayout = getLayout; interface PostParams extends ParsedUrlQuery { slug: string; @@ -70,9 +67,11 @@ export const getStaticProps: GetStaticProps = async ( ); const { slug } = context.params as PostParams; const post = await getPostBySlug(slug); + const breadcrumbTitle = post.title; return { props: { + breadcrumbTitle, post, translation, }, diff --git a/src/pages/blog/index.tsx b/src/pages/blog/index.tsx index 7d34763..23013bd 100644 --- a/src/pages/blog/index.tsx +++ b/src/pages/blog/index.tsx @@ -1,8 +1,7 @@ -import { ReactElement } from 'react'; import { GetStaticProps } from 'next'; import Head from 'next/head'; import { t } from '@lingui/macro'; -import Layout from '@components/Layouts/Layout'; +import { getLayout } from '@components/Layouts/Layout'; import { seo } from '@config/seo'; import { config } from '@config/website'; import { NextPageWithLayout } from '@ts/types/app'; @@ -62,9 +61,7 @@ const Blog: NextPageWithLayout<BlogPageProps> = ({ fallback }) => { ); }; -Blog.getLayout = function getLayout(page: ReactElement) { - return <Layout>{page}</Layout>; -}; +Blog.getLayout = getLayout; export const getStaticProps: GetStaticProps = async (context) => { const translation = await loadTranslation( @@ -72,9 +69,11 @@ export const getStaticProps: GetStaticProps = async (context) => { process.env.NODE_ENV === 'production' ); const data = await getPublishedPosts({ first: config.postsPerPage }); + const breadcrumbTitle = t`Blog`; return { props: { + breadcrumbTitle, fallback: { '/api/posts': data, }, diff --git a/src/pages/contact.tsx b/src/pages/contact.tsx index ff60188..8e6de7a 100644 --- a/src/pages/contact.tsx +++ b/src/pages/contact.tsx @@ -1,6 +1,6 @@ import { ButtonSubmit } from '@components/Buttons'; import { Form, FormItem, Input, TextArea } from '@components/Form'; -import Layout from '@components/Layouts/Layout'; +import { getLayout } from '@components/Layouts/Layout'; import { seo } from '@config/seo'; import { t } from '@lingui/macro'; import { sendMail } from '@services/graphql/mutations'; @@ -8,7 +8,7 @@ import { NextPageWithLayout } from '@ts/types/app'; import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticProps, GetStaticPropsContext } from 'next'; import Head from 'next/head'; -import { FormEvent, ReactElement, useState } from 'react'; +import { FormEvent, useState } from 'react'; const ContactPage: NextPageWithLayout = () => { const [name, setName] = useState(''); @@ -110,7 +110,7 @@ const ContactPage: NextPageWithLayout = () => { ); }; -ContactPage.getLayout = (page: ReactElement) => <Layout>{page}</Layout>; +ContactPage.getLayout = getLayout; export const getStaticProps: GetStaticProps = async ( context: GetStaticPropsContext @@ -120,8 +120,11 @@ export const getStaticProps: GetStaticProps = async ( process.env.NODE_ENV === 'production' ); + const breadcrumbTitle = t`Contact`; + return { props: { + breadcrumbTitle, translation, }, }; diff --git a/src/pages/cv.tsx b/src/pages/cv.tsx index 150e29a..de63ec6 100644 --- a/src/pages/cv.tsx +++ b/src/pages/cv.tsx @@ -1,4 +1,4 @@ -import Layout from '@components/Layouts/Layout'; +import { getLayout } from '@components/Layouts/Layout'; import { seo } from '@config/seo'; import { getPageByUri } from '@services/graphql/queries'; import { NextPageWithLayout } from '@ts/types/app'; @@ -6,7 +6,6 @@ import { PageProps } from '@ts/types/pages'; import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticProps, GetStaticPropsContext } from 'next'; import Head from 'next/head'; -import { ReactElement } from 'react'; const CV: NextPageWithLayout<PageProps> = ({ page }) => { return ( @@ -26,7 +25,7 @@ const CV: NextPageWithLayout<PageProps> = ({ page }) => { ); }; -CV.getLayout = (page: ReactElement) => <Layout>{page}</Layout>; +CV.getLayout = getLayout; export const getStaticProps: GetStaticProps = async ( context: GetStaticPropsContext @@ -36,9 +35,11 @@ export const getStaticProps: GetStaticProps = async ( process.env.NODE_ENV === 'production' ); const page = await getPageByUri('/cv/'); + const breadcrumbTitle = page.title; return { props: { + breadcrumbTitle, page, translation, }, diff --git a/src/pages/mentions-legales.tsx b/src/pages/mentions-legales.tsx index c90b8d6..6155132 100644 --- a/src/pages/mentions-legales.tsx +++ b/src/pages/mentions-legales.tsx @@ -1,4 +1,4 @@ -import Layout from '@components/Layouts/Layout'; +import { getLayout } from '@components/Layouts/Layout'; import { seo } from '@config/seo'; import { getPageByUri } from '@services/graphql/queries'; import { NextPageWithLayout } from '@ts/types/app'; @@ -6,7 +6,6 @@ import { PageProps } from '@ts/types/pages'; import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticProps, GetStaticPropsContext } from 'next'; import Head from 'next/head'; -import { ReactElement } from 'react'; const LegalNotice: NextPageWithLayout<PageProps> = ({ page }) => { return ( @@ -26,7 +25,7 @@ const LegalNotice: NextPageWithLayout<PageProps> = ({ page }) => { ); }; -LegalNotice.getLayout = (page: ReactElement) => <Layout>{page}</Layout>; +LegalNotice.getLayout = getLayout; export const getStaticProps: GetStaticProps = async ( context: GetStaticPropsContext @@ -36,9 +35,11 @@ export const getStaticProps: GetStaticProps = async ( process.env.NODE_ENV === 'production' ); const page = await getPageByUri('/mentions-legales/'); + const breadcrumbTitle = page.title; return { props: { + breadcrumbTitle, page, translation, }, diff --git a/src/pages/recherche/index.tsx b/src/pages/recherche/index.tsx index 6de5816..b39d3f9 100644 --- a/src/pages/recherche/index.tsx +++ b/src/pages/recherche/index.tsx @@ -1,5 +1,5 @@ import { Button } from '@components/Buttons'; -import Layout from '@components/Layouts/Layout'; +import { getLayout } from '@components/Layouts/Layout'; import PostsList from '@components/PostsList/PostsList'; import { config } from '@config/website'; import { t } from '@lingui/macro'; @@ -10,7 +10,7 @@ import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticProps } from 'next'; import Head from 'next/head'; import { useRouter } from 'next/router'; -import { ReactElement, useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import useSWRInfinite from 'swr/infinite'; const Search: NextPageWithLayout = () => { @@ -92,7 +92,7 @@ const Search: NextPageWithLayout = () => { ); }; -Search.getLayout = (page: ReactElement) => <Layout>{page}</Layout>; +Search.getLayout = getLayout; export const getStaticProps: GetStaticProps = async (context) => { const translation = await loadTranslation( @@ -100,8 +100,11 @@ export const getStaticProps: GetStaticProps = async (context) => { process.env.NODE_ENV === 'production' ); + const breadcrumbTitle = t`Search`; + return { props: { + breadcrumbTitle, translation, }, }; diff --git a/src/pages/sujet/[slug].tsx b/src/pages/sujet/[slug].tsx index 4dc4e9b..f6571e1 100644 --- a/src/pages/sujet/[slug].tsx +++ b/src/pages/sujet/[slug].tsx @@ -1,4 +1,4 @@ -import Layout from '@components/Layouts/Layout'; +import { getLayout } from '@components/Layouts/Layout'; import PostPreview from '@components/PostPreview/PostPreview'; import { t } from '@lingui/macro'; import { NextPageWithLayout } from '@ts/types/app'; @@ -7,7 +7,6 @@ import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next'; import Image from 'next/image'; import { ParsedUrlQuery } from 'querystring'; -import { ReactElement } from 'react'; import styles from '@styles/pages/Subject.module.scss'; import { getAllSubjectsSlug, @@ -57,9 +56,7 @@ const Subject: NextPageWithLayout<SubjectProps> = ({ subject }) => { ); }; -Subject.getLayout = function getLayout(page: ReactElement) { - return <Layout>{page}</Layout>; -}; +Subject.getLayout = getLayout; interface PostParams extends ParsedUrlQuery { slug: string; @@ -74,9 +71,11 @@ export const getStaticProps: GetStaticProps = async ( ); const { slug } = context.params as PostParams; const subject = await getSubjectBySlug(slug); + const breadcrumbTitle = subject.title; return { props: { + breadcrumbTitle, subject, translation, }, diff --git a/src/pages/thematique/[slug].tsx b/src/pages/thematique/[slug].tsx index 2e7c346..51506e5 100644 --- a/src/pages/thematique/[slug].tsx +++ b/src/pages/thematique/[slug].tsx @@ -1,4 +1,4 @@ -import Layout from '@components/Layouts/Layout'; +import { getLayout } from '@components/Layouts/Layout'; import PostPreview from '@components/PostPreview/PostPreview'; import { t } from '@lingui/macro'; import { NextPageWithLayout } from '@ts/types/app'; @@ -6,7 +6,6 @@ import { ThematicProps } from '@ts/types/taxonomies'; import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next'; import { ParsedUrlQuery } from 'querystring'; -import { ReactElement } from 'react'; import styles from '@styles/pages/Thematic.module.scss'; import { getAllThematicsSlug, @@ -39,9 +38,7 @@ const Thematic: NextPageWithLayout<ThematicProps> = ({ thematic }) => { ); }; -Thematic.getLayout = function getLayout(page: ReactElement) { - return <Layout>{page}</Layout>; -}; +Thematic.getLayout = getLayout; interface PostParams extends ParsedUrlQuery { slug: string; @@ -56,9 +53,11 @@ export const getStaticProps: GetStaticProps = async ( ); const { slug } = context.params as PostParams; const thematic = await getThematicBySlug(slug); + const breadcrumbTitle = thematic.title; return { props: { + breadcrumbTitle, thematic, translation, }, |
