aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/templates/layout
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/templates/layout')
-rw-r--r--src/components/templates/layout/layout.stories.tsx54
-rw-r--r--src/components/templates/layout/layout.test.tsx12
-rw-r--r--src/components/templates/layout/layout.tsx26
3 files changed, 70 insertions, 22 deletions
diff --git a/src/components/templates/layout/layout.stories.tsx b/src/components/templates/layout/layout.stories.tsx
index 2415412..105e808 100644
--- a/src/components/templates/layout/layout.stories.tsx
+++ b/src/components/templates/layout/layout.stories.tsx
@@ -1,5 +1,4 @@
import { ComponentMeta, ComponentStory } from '@storybook/react';
-import { IntlProvider } from 'react-intl';
import LayoutComponent from './layout';
/**
@@ -8,6 +7,10 @@ import LayoutComponent from './layout';
export default {
title: 'Templates/LayoutBase',
component: LayoutComponent,
+ args: {
+ breadcrumbSchema: [],
+ isHome: false,
+ },
argTypes: {
children: {
control: {
@@ -19,6 +22,31 @@ export default {
required: true,
},
},
+ breadcrumbSchema: {
+ control: {
+ type: 'null',
+ },
+ description: 'The JSON schema for breadcrumb items.',
+ type: {
+ name: 'object',
+ required: true,
+ value: {},
+ },
+ },
+ isHome: {
+ control: {
+ type: 'boolean',
+ },
+ description: 'Determine if it is the homepage.',
+ table: {
+ category: 'Options',
+ defaultValue: { summary: false },
+ },
+ type: {
+ name: 'boolean',
+ required: false,
+ },
+ },
className: {
control: {
type: 'text',
@@ -35,19 +63,17 @@ export default {
},
decorators: [
(Story) => (
- <IntlProvider locale="en">
- <div
- id="__next"
- style={{
- flex: 1,
- display: 'flex',
- flexFlow: 'column nowrap',
- minHeight: '100vh',
- }}
- >
- <Story />
- </div>
- </IntlProvider>
+ <div
+ id="__next"
+ style={{
+ flex: 1,
+ display: 'flex',
+ flexFlow: 'column nowrap',
+ minHeight: '100vh',
+ }}
+ >
+ <Story />
+ </div>
),
],
parameters: {
diff --git a/src/components/templates/layout/layout.test.tsx b/src/components/templates/layout/layout.test.tsx
index 914e1cd..94145ec 100644
--- a/src/components/templates/layout/layout.test.tsx
+++ b/src/components/templates/layout/layout.test.tsx
@@ -1,34 +1,36 @@
import { render, screen } from '@test-utils';
+import { BreadcrumbList } from 'schema-dts';
import Layout from './layout';
const body =
'Sit dolorem eveniet. Sit sit odio nemo vitae corrupti modi sint est rerum. Pariatur quidem maiores distinctio. Quia et illum aspernatur est cum.';
+const breadcrumbSchema: BreadcrumbList['itemListElement'][] = [];
describe('Layout', () => {
it('renders the website header', () => {
- render(<Layout>{body}</Layout>);
+ render(<Layout breadcrumbSchema={breadcrumbSchema}>{body}</Layout>);
expect(screen.getByRole('banner')).toBeInTheDocument();
});
it('renders the website main content', () => {
- render(<Layout>{body}</Layout>);
+ render(<Layout breadcrumbSchema={breadcrumbSchema}>{body}</Layout>);
expect(screen.getByRole('main')).toBeInTheDocument();
});
it('renders the website footer', () => {
- render(<Layout>{body}</Layout>);
+ render(<Layout breadcrumbSchema={breadcrumbSchema}>{body}</Layout>);
expect(screen.getByRole('contentinfo')).toBeInTheDocument();
});
it('renders a skip to content link', () => {
- render(<Layout>{body}</Layout>);
+ render(<Layout breadcrumbSchema={breadcrumbSchema}>{body}</Layout>);
expect(
screen.getByRole('link', { name: 'Skip to content' })
).toBeInTheDocument();
});
it('renders an article', () => {
- render(<Layout>{body}</Layout>);
+ render(<Layout breadcrumbSchema={breadcrumbSchema}>{body}</Layout>);
expect(screen.getByRole('article')).toHaveTextContent(body);
});
});
diff --git a/src/components/templates/layout/layout.tsx b/src/components/templates/layout/layout.tsx
index bfb918b..9e9282b 100644
--- a/src/components/templates/layout/layout.tsx
+++ b/src/components/templates/layout/layout.tsx
@@ -13,7 +13,13 @@ import useSettings from '@utils/hooks/use-settings';
import Script from 'next/script';
import { FC, ReactNode } from 'react';
import { useIntl } from 'react-intl';
-import { Person, SearchAction, WebSite, WithContext } from 'schema-dts';
+import {
+ BreadcrumbList,
+ Person,
+ SearchAction,
+ WebSite,
+ WithContext,
+} from 'schema-dts';
import styles from './layout.module.scss';
export type QueryAction = SearchAction & {
@@ -22,6 +28,10 @@ export type QueryAction = SearchAction & {
export type LayoutProps = Pick<HeaderProps, 'isHome'> & {
/**
+ * The breadcrumb JSON schema.
+ */
+ breadcrumbSchema: BreadcrumbList['itemListElement'][];
+ /**
* The layout main content.
*/
children: ReactNode;
@@ -36,7 +46,12 @@ export type LayoutProps = Pick<HeaderProps, 'isHome'> & {
*
* Render the base layout used by all pages.
*/
-const Layout: FC<LayoutProps> = ({ children, isHome, ...props }) => {
+const Layout: FC<LayoutProps> = ({
+ breadcrumbSchema,
+ children,
+ isHome,
+ ...props
+}) => {
const intl = useIntl();
const { website } = useSettings();
const { baseline, copyright, locales, name, picture, url } = website;
@@ -153,12 +168,17 @@ const Layout: FC<LayoutProps> = ({ children, isHome, ...props }) => {
id="schema-layout"
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
- ></Script>
+ />
<Script
id="schema-branding"
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(brandingSchema) }}
/>
+ <Script
+ id="schema-breadcrumb"
+ type="application/ld+json"
+ dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbSchema) }}
+ />
<noscript>
<div className={styles['noscript-spacing']}></div>
</noscript>