aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/components/molecules/card/card.stories.tsx261
-rw-r--r--src/components/molecules/card/card.test.tsx13
-rw-r--r--src/components/molecules/layout/page-footer.stories.tsx23
-rw-r--r--src/components/molecules/layout/page-footer.test.tsx4
-rw-r--r--src/components/molecules/layout/page-footer.tsx13
-rw-r--r--src/components/molecules/layout/page-header.stories.tsx83
-rw-r--r--src/components/molecules/layout/page-header.test.tsx8
-rw-r--r--src/components/molecules/layout/page-header.tsx7
-rw-r--r--src/components/molecules/meta-list/meta-list.stories.tsx9
-rw-r--r--src/components/molecules/meta-list/meta-list.test.tsx63
-rw-r--r--src/components/molecules/meta-list/meta-list.tsx72
-rw-r--r--src/components/organisms/comment/approved-comment/approved-comment.tsx26
-rw-r--r--src/components/organisms/post-preview/post-preview-meta/post-preview-meta.tsx220
-rw-r--r--src/components/organisms/project-overview/project-overview.tsx40
-rw-r--r--src/components/templates/page/page-layout.stories.tsx74
-rw-r--r--src/components/templates/page/page-layout.tsx15
-rw-r--r--src/i18n/en.json40
-rw-r--r--src/i18n/fr.json40
-rw-r--r--src/pages/article/[slug].tsx194
-rw-r--r--src/pages/blog/index.tsx47
-rw-r--r--src/pages/blog/page/[number].tsx47
-rw-r--r--src/pages/cv.tsx54
-rw-r--r--src/pages/index.tsx21
-rw-r--r--src/pages/mentions-legales.tsx54
-rw-r--r--src/pages/projets/[slug].tsx54
-rw-r--r--src/pages/projets/index.tsx26
-rw-r--r--src/pages/recherche/index.tsx47
-rw-r--r--src/pages/sujet/[slug].tsx114
-rw-r--r--src/pages/thematique/[slug].tsx92
29 files changed, 787 insertions, 974 deletions
diff --git a/src/components/molecules/card/card.stories.tsx b/src/components/molecules/card/card.stories.tsx
index bc9cbd4..7cc2ad4 100644
--- a/src/components/molecules/card/card.stories.tsx
+++ b/src/components/molecules/card/card.stories.tsx
@@ -1,6 +1,7 @@
import type { ComponentMeta, Story } from '@storybook/react';
import NextImage from 'next/image';
import { Button, ButtonLink, Link, Time } from '../../atoms';
+import { MetaItem } from '../meta-list';
import { Card, type CardProps } from './card';
import { CardActions } from './card-actions';
import { CardBody } from './card-body';
@@ -71,17 +72,13 @@ export const HeaderMeta = Template.bind({});
HeaderMeta.args = {
children: (
<CardHeader>
- <CardMeta
- isInline
- items={[
- { id: 'author', label: 'Written by:', value: 'The author' },
- {
- id: 'publication-date',
- label: 'Published on:',
- value: <Time date={new Date().toISOString()} />,
- },
- ]}
- />
+ <CardMeta isInline>
+ <MetaItem label="Written by:" value="The author" />
+ <MetaItem
+ label="Published on:"
+ value={<Time date={new Date().toISOString()} />}
+ />
+ </CardMeta>
</CardHeader>
),
};
@@ -107,27 +104,23 @@ export const FooterMeta = Template.bind({});
FooterMeta.args = {
children: <CardFooter />,
meta: (
- <CardMeta
- items={[
- {
- id: 'categories',
- label: 'Categories:',
- value: [
- { id: 'cat-1', value: <Link href="#cat1">Category 1</Link> },
- { id: 'cat-2', value: <Link href="#cat2">Category 2</Link> },
- ],
- },
- {
- id: 'tags',
- label: 'Tags:',
- value: [
- { id: 'tag-1', value: 'Tag 1' },
- { id: 'tag-2', value: 'Tag 2' },
- { id: 'tag-3', value: 'Tag 3' },
- ],
- },
- ]}
- />
+ <CardMeta>
+ <MetaItem
+ label="Categories:"
+ value={[
+ { id: 'cat-1', value: <Link href="#cat1">Category 1</Link> },
+ { id: 'cat-2', value: <Link href="#cat2">Category 2</Link> },
+ ]}
+ />
+ <MetaItem
+ label="Tags:"
+ value={[
+ { id: 'tag-1', value: 'Tag 1' },
+ { id: 'tag-2', value: 'Tag 2' },
+ { id: 'tag-3', value: 'Tag 3' },
+ ]}
+ />
+ </CardMeta>
),
};
@@ -155,17 +148,13 @@ CompositionTitleMeta.args = {
children: (
<CardHeader>
<CardTitle>The card title</CardTitle>
- <CardMeta
- isInline
- items={[
- { id: 'author', label: 'Written by:', value: 'The author' },
- {
- id: 'publication-date',
- label: 'Published on:',
- value: <Time date={new Date().toISOString()} />,
- },
- ]}
- />
+ <CardMeta isInline>
+ <MetaItem label="Written by:" value="The author" />
+ <MetaItem
+ label="Published on:"
+ value={<Time date={new Date().toISOString()} />}
+ />
+ </CardMeta>
</CardHeader>
),
};
@@ -175,17 +164,13 @@ CompositionCoverTitleMeta.args = {
children: (
<CardHeader>
<CardTitle>The card title</CardTitle>
- <CardMeta
- isInline
- items={[
- { id: 'author', label: 'Written by:', value: 'The author' },
- {
- id: 'publication-date',
- label: 'Published on:',
- value: <Time date={new Date().toISOString()} />,
- },
- ]}
- />
+ <CardMeta isInline>
+ <MetaItem label="Written by:" value="The author" />
+ <MetaItem
+ label="Published on:"
+ value={<Time date={new Date().toISOString()} />}
+ />
+ </CardMeta>
</CardHeader>
),
cover: (
@@ -250,17 +235,13 @@ CompositionTitleMetaBody.args = {
<>
<CardHeader>
<CardTitle>The card title</CardTitle>
- <CardMeta
- isInline
- items={[
- { id: 'author', label: 'Written by:', value: 'The author' },
- {
- id: 'publication-date',
- label: 'Published on:',
- value: <Time date={new Date().toISOString()} />,
- },
- ]}
- />
+ <CardMeta isInline>
+ <MetaItem label="Written by:" value="The author" />
+ <MetaItem
+ label="Published on:"
+ value={<Time date={new Date().toISOString()} />}
+ />
+ </CardMeta>
</CardHeader>
<CardBody>
Nihil magnam tempora voluptatem. Reiciendis ut cum vel. Odit et
@@ -278,17 +259,13 @@ CompositionCoverTitleMetaBody.args = {
<>
<CardHeader>
<CardTitle>The card title</CardTitle>
- <CardMeta
- isInline
- items={[
- { id: 'author', label: 'Written by:', value: 'The author' },
- {
- id: 'publication-date',
- label: 'Published on:',
- value: <Time date={new Date().toISOString()} />,
- },
- ]}
- />
+ <CardMeta isInline>
+ <MetaItem label="Written by:" value="The author" />
+ <MetaItem
+ label="Published on:"
+ value={<Time date={new Date().toISOString()} />}
+ />
+ </CardMeta>
</CardHeader>
<CardBody>
Nihil magnam tempora voluptatem. Reiciendis ut cum vel. Odit et
@@ -399,27 +376,23 @@ CompositionTitleBodyActionsMeta.args = {
</>
),
meta: (
- <CardMeta
- items={[
- {
- id: 'categories',
- label: 'Categories:',
- value: [
- { id: 'cat-1', value: <Link href="#cat1">Category 1</Link> },
- { id: 'cat-2', value: <Link href="#cat2">Category 2</Link> },
- ],
- },
- {
- id: 'tags',
- label: 'Tags:',
- value: [
- { id: 'tag-1', value: 'Tag 1' },
- { id: 'tag-2', value: 'Tag 2' },
- { id: 'tag-3', value: 'Tag 3' },
- ],
- },
- ]}
- />
+ <CardMeta>
+ <MetaItem
+ label="Categories:"
+ value={[
+ { id: 'cat-1', value: <Link href="#cat1">Category 1</Link> },
+ { id: 'cat-2', value: <Link href="#cat2">Category 2</Link> },
+ ]}
+ />
+ <MetaItem
+ label="Tags:"
+ value={[
+ { id: 'tag-1', value: 'Tag 1' },
+ { id: 'tag-2', value: 'Tag 2' },
+ { id: 'tag-3', value: 'Tag 3' },
+ ]}
+ />
+ </CardMeta>
),
};
@@ -455,27 +428,23 @@ CompositionCoverTitleBodyActionsMeta.args = {
</CardCover>
),
meta: (
- <CardMeta
- items={[
- {
- id: 'categories',
- label: 'Categories:',
- value: [
- { id: 'cat-1', value: <Link href="#cat1">Category 1</Link> },
- { id: 'cat-2', value: <Link href="#cat2">Category 2</Link> },
- ],
- },
- {
- id: 'tags',
- label: 'Tags:',
- value: [
- { id: 'tag-1', value: 'Tag 1' },
- { id: 'tag-2', value: 'Tag 2' },
- { id: 'tag-3', value: 'Tag 3' },
- ],
- },
- ]}
- />
+ <CardMeta>
+ <MetaItem
+ label="Categories:"
+ value={[
+ { id: 'cat-1', value: <Link href="#cat1">Category 1</Link> },
+ { id: 'cat-2', value: <Link href="#cat2">Category 2</Link> },
+ ]}
+ />
+ <MetaItem
+ label="Tags:"
+ value={[
+ { id: 'tag-1', value: 'Tag 1' },
+ { id: 'tag-2', value: 'Tag 2' },
+ { id: 'tag-3', value: 'Tag 3' },
+ ]}
+ />
+ </CardMeta>
),
};
@@ -485,17 +454,13 @@ CompositionAllContents.args = {
<>
<CardHeader>
<CardTitle>The card title</CardTitle>
- <CardMeta
- isInline
- items={[
- { id: 'author', label: 'Written by:', value: 'The author' },
- {
- id: 'publication-date',
- label: 'Published on:',
- value: <Time date={new Date().toISOString()} />,
- },
- ]}
- />
+ <CardMeta isInline>
+ <MetaItem label="Written by:" value="The author" />
+ <MetaItem
+ label="Published on:"
+ value={<Time date={new Date().toISOString()} />}
+ />
+ </CardMeta>
</CardHeader>
<CardBody>
Nihil magnam tempora voluptatem. Reiciendis ut cum vel. Odit et
@@ -522,26 +487,22 @@ CompositionAllContents.args = {
</CardCover>
),
meta: (
- <CardMeta
- items={[
- {
- id: 'categories',
- label: 'Categories:',
- value: [
- { id: 'cat-1', value: <Link href="#cat1">Category 1</Link> },
- { id: 'cat-2', value: <Link href="#cat2">Category 2</Link> },
- ],
- },
- {
- id: 'tags',
- label: 'Tags:',
- value: [
- { id: 'tag-1', value: 'Tag 1' },
- { id: 'tag-2', value: 'Tag 2' },
- { id: 'tag-3', value: 'Tag 3' },
- ],
- },
- ]}
- />
+ <CardMeta>
+ <MetaItem
+ label="Categories:"
+ value={[
+ { id: 'cat-1', value: <Link href="#cat1">Category 1</Link> },
+ { id: 'cat-2', value: <Link href="#cat2">Category 2</Link> },
+ ]}
+ />
+ <MetaItem
+ label="Tags:"
+ value={[
+ { id: 'tag-1', value: 'Tag 1' },
+ { id: 'tag-2', value: 'Tag 2' },
+ { id: 'tag-3', value: 'Tag 3' },
+ ]}
+ />
+ </CardMeta>
),
};
diff --git a/src/components/molecules/card/card.test.tsx b/src/components/molecules/card/card.test.tsx
index 40a5830..769185b 100644
--- a/src/components/molecules/card/card.test.tsx
+++ b/src/components/molecules/card/card.test.tsx
@@ -1,6 +1,7 @@
import { describe, expect, it } from '@jest/globals';
import { render, screen as rtlScreen } from '@testing-library/react';
import NextImage from 'next/image';
+import { MetaItem } from '../meta-list';
import { Card } from './card';
import { CardFooter } from './card-footer';
import { CardHeader } from './card-header';
@@ -66,7 +67,11 @@ describe('Card', () => {
render(
<Card
- meta={<CardMeta items={[{ id: 'any', label: term, value: desc }]} />}
+ meta={
+ <CardMeta>
+ <MetaItem label={term} value={desc} />
+ </CardMeta>
+ }
>
<CardFooter />
</Card>
@@ -83,7 +88,11 @@ describe('Card', () => {
render(
<Card
- meta={<CardMeta items={[{ id: 'any', label: term, value: desc }]} />}
+ meta={
+ <CardMeta>
+ <MetaItem label={term} value={desc} />
+ </CardMeta>
+ }
>
{body}
</Card>
diff --git a/src/components/molecules/layout/page-footer.stories.tsx b/src/components/molecules/layout/page-footer.stories.tsx
index 48c8c17..994e888 100644
--- a/src/components/molecules/layout/page-footer.stories.tsx
+++ b/src/components/molecules/layout/page-footer.stories.tsx
@@ -1,4 +1,6 @@
import type { ComponentMeta, ComponentStory } from '@storybook/react';
+import { Link } from '../../atoms';
+import { MetaItem, MetaList } from '../meta-list';
import { PageFooter as PageFooterComponent } from './page-footer';
/**
@@ -39,22 +41,17 @@ const Template: ComponentStory<typeof PageFooterComponent> = (args) => (
<PageFooterComponent {...args} />
);
-const meta = [
- {
- id: 'more-about',
- label: 'More posts about:',
- value: (
- <a key="topic-1" href="#topic1">
- Topic name
- </a>
- ),
- },
-];
-
/**
* Page Footer Stories - With meta
*/
export const PageFooter = Template.bind({});
PageFooter.args = {
- meta,
+ children: (
+ <MetaList>
+ <MetaItem
+ label="More posts about:"
+ value={<Link href="#topic1">Topic name</Link>}
+ />
+ </MetaList>
+ ),
};
diff --git a/src/components/molecules/layout/page-footer.test.tsx b/src/components/molecules/layout/page-footer.test.tsx
index 7f0bcd5..dbd20f5 100644
--- a/src/components/molecules/layout/page-footer.test.tsx
+++ b/src/components/molecules/layout/page-footer.test.tsx
@@ -1,10 +1,10 @@
import { describe, expect, it } from '@jest/globals';
-import { render, screen } from '../../../../tests/utils';
+import { render, screen as rtlScreen } from '../../../../tests/utils';
import { PageFooter } from './page-footer';
describe('PageFooter', () => {
it('renders a footer element', () => {
render(<PageFooter />);
- expect(screen.getByRole('contentinfo')).toBeInTheDocument();
+ expect(rtlScreen.getByRole('contentinfo')).toBeInTheDocument();
});
});
diff --git a/src/components/molecules/layout/page-footer.tsx b/src/components/molecules/layout/page-footer.tsx
index a93fced..e0ce2ef 100644
--- a/src/components/molecules/layout/page-footer.tsx
+++ b/src/components/molecules/layout/page-footer.tsx
@@ -1,12 +1,11 @@
-import type { FC } from 'react';
+import type { FC, ReactNode } from 'react';
import { Footer, type FooterProps } from '../../atoms';
-import { MetaList, type MetaItemData } from '../meta-list';
export type PageFooterProps = Omit<FooterProps, 'children'> & {
/**
- * The footer metadata.
+ * The footer contents.
*/
- meta?: MetaItemData[];
+ children?: ReactNode;
};
/**
@@ -14,8 +13,6 @@ export type PageFooterProps = Omit<FooterProps, 'children'> & {
*
* Render a footer to display page meta.
*/
-export const PageFooter: FC<PageFooterProps> = ({ meta, ...props }) => (
- <Footer {...props}>
- {meta ? <MetaList hasInlinedValues items={meta} /> : null}
- </Footer>
+export const PageFooter: FC<PageFooterProps> = ({ children, ...props }) => (
+ <Footer {...props}>{children}</Footer>
);
diff --git a/src/components/molecules/layout/page-header.stories.tsx b/src/components/molecules/layout/page-header.stories.tsx
index 54d5fe8..97eae5a 100644
--- a/src/components/molecules/layout/page-header.stories.tsx
+++ b/src/components/molecules/layout/page-header.stories.tsx
@@ -1,4 +1,5 @@
import type { ComponentMeta, ComponentStory } from '@storybook/react';
+import { MetaItem, MetaList } from '../meta-list';
import { PageHeader } from './page-header';
/**
@@ -62,32 +63,6 @@ const Template: ComponentStory<typeof PageHeader> = (args) => (
<PageHeader {...args} />
);
-const meta = [
- { id: 'publication-date', label: 'Published on:', value: '2022-04-09' },
- {
- id: 'thematics',
- label: 'Thematics:',
- value: [
- {
- id: 'cat-1',
- value: (
- <a key="category1" href="#cat1">
- Category 1
- </a>
- ),
- },
- {
- id: 'cat-2',
- value: (
- <a key="category2" href="#cat2">
- Category 2
- </a>
- ),
- },
- ],
- },
-];
-
/**
* Page Header Stories - Default
*/
@@ -111,7 +86,33 @@ WithIntro.args = {
*/
export const WithMeta = Template.bind({});
WithMeta.args = {
- meta,
+ meta: (
+ <MetaList>
+ <MetaItem isInline label="Published on:" value="2022-04-09" />
+ <MetaItem
+ isInline
+ label="Thematics:"
+ value={[
+ {
+ id: 'cat-1',
+ value: (
+ <a key="category1" href="#cat1">
+ Category 1
+ </a>
+ ),
+ },
+ {
+ id: 'cat-2',
+ value: (
+ <a key="category2" href="#cat2">
+ Category 2
+ </a>
+ ),
+ },
+ ]}
+ />
+ </MetaList>
+ ),
title: 'Excepturi nesciunt illum',
};
@@ -122,6 +123,32 @@ export const WithIntroAndMeta = Template.bind({});
WithIntroAndMeta.args = {
intro:
'Minima dolor nihil. Velit atque odit totam enim. Quisquam reprehenderit ut et inventore et nihil libero exercitationem. Cumque similique magni placeat et. Et sed est cumque labore. Et quia similique.',
- meta,
+ meta: (
+ <MetaList>
+ <MetaItem isInline label="Published on:" value="2022-04-09" />
+ <MetaItem
+ isInline
+ label="Thematics:"
+ value={[
+ {
+ id: 'cat-1',
+ value: (
+ <a key="category1" href="#cat1">
+ Category 1
+ </a>
+ ),
+ },
+ {
+ id: 'cat-2',
+ value: (
+ <a key="category2" href="#cat2">
+ Category 2
+ </a>
+ ),
+ },
+ ]}
+ />
+ </MetaList>
+ ),
title: 'Excepturi nesciunt illum',
};
diff --git a/src/components/molecules/layout/page-header.test.tsx b/src/components/molecules/layout/page-header.test.tsx
index 1f1a139..82aa7e1 100644
--- a/src/components/molecules/layout/page-header.test.tsx
+++ b/src/components/molecules/layout/page-header.test.tsx
@@ -1,5 +1,5 @@
import { describe, expect, it } from '@jest/globals';
-import { render, screen } from '../../../../tests/utils';
+import { render, screen as rtlScreen } from '../../../../tests/utils';
import { PageHeader } from './page-header';
const title = 'Non nemo amet';
@@ -9,11 +9,13 @@ const intro =
describe('PageHeader', () => {
it('renders a title', () => {
render(<PageHeader title={title} intro={intro} />);
- expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent(title);
+ expect(rtlScreen.getByRole('heading', { level: 1 })).toHaveTextContent(
+ title
+ );
});
it('renders an introduction', () => {
render(<PageHeader title={title} intro={intro} />);
- expect(screen.getByText(intro)).toBeInTheDocument();
+ expect(rtlScreen.getByText(intro)).toBeInTheDocument();
});
});
diff --git a/src/components/molecules/layout/page-header.tsx b/src/components/molecules/layout/page-header.tsx
index ea0dd2c..e70d66c 100644
--- a/src/components/molecules/layout/page-header.tsx
+++ b/src/components/molecules/layout/page-header.tsx
@@ -1,6 +1,5 @@
import type { FC, ReactNode } from 'react';
import { Header, Heading } from '../../atoms';
-import { MetaList, type MetaItemData } from '../meta-list';
import styles from './page-header.module.scss';
export type PageHeaderProps = {
@@ -15,7 +14,7 @@ export type PageHeaderProps = {
/**
* The page metadata.
*/
- meta?: MetaItemData[];
+ meta?: ReactNode;
/**
* The page title.
*/
@@ -55,9 +54,7 @@ export const PageHeader: FC<PageHeaderProps> = ({
<Heading className={styles.title} level={1}>
{title}
</Heading>
- {meta ? (
- <MetaList className={styles.meta} hasInlinedItems items={meta} />
- ) : null}
+ {meta}
{intro ? getIntro() : null}
</div>
</Header>
diff --git a/src/components/molecules/meta-list/meta-list.stories.tsx b/src/components/molecules/meta-list/meta-list.stories.tsx
index 463ec96..d73c5b9 100644
--- a/src/components/molecules/meta-list/meta-list.stories.tsx
+++ b/src/components/molecules/meta-list/meta-list.stories.tsx
@@ -1,6 +1,7 @@
import type { ComponentMeta, ComponentStory } from '@storybook/react';
import { Link } from '../../atoms';
-import { type MetaItemData, MetaList } from './meta-list';
+import { MetaItem } from './meta-item';
+import { MetaList } from './meta-list';
/**
* MetaList - Storybook Meta
@@ -24,7 +25,7 @@ const Template: ComponentStory<typeof MetaList> = (args) => (
<MetaList {...args} />
);
-const items: MetaItemData[] = [
+const items = [
{ id: 'comments', label: 'Comments', value: 'No comments.' },
{
id: 'category',
@@ -57,7 +58,7 @@ const items: MetaItemData[] = [
*/
export const Default = Template.bind({});
Default.args = {
- items,
+ children: items.map(({ id, ...item }) => <MetaItem key={id} {...item} />),
};
/**
@@ -65,6 +66,6 @@ Default.args = {
*/
export const Inlined = Template.bind({});
Inlined.args = {
+ children: items.map(({ id, ...item }) => <MetaItem key={id} {...item} />),
isInline: true,
- items,
};
diff --git a/src/components/molecules/meta-list/meta-list.test.tsx b/src/components/molecules/meta-list/meta-list.test.tsx
index cc4d2fa..e4e2860 100644
--- a/src/components/molecules/meta-list/meta-list.test.tsx
+++ b/src/components/molecules/meta-list/meta-list.test.tsx
@@ -1,31 +1,44 @@
import { describe, expect, it } from '@jest/globals';
import { render, screen as rtlScreen } from '@testing-library/react';
-import { type MetaItemData, MetaList } from './meta-list';
+import { MetaItem } from './meta-item';
+import { MetaList } from './meta-list';
describe('MetaList', () => {
it('renders a list of meta items', () => {
- const items: MetaItemData[] = [
+ const items = [
{ id: 'item1', label: 'Item 1', value: 'Value 1' },
{ id: 'item2', label: 'Item 2', value: 'Value 2' },
{ id: 'item3', label: 'Item 3', value: 'Value 3' },
{ id: 'item4', label: 'Item 4', value: 'Value 4' },
];
- render(<MetaList items={items} />);
+ render(
+ <MetaList>
+ {items.map(({ id, ...item }) => (
+ <MetaItem key={id} {...item} />
+ ))}
+ </MetaList>
+ );
expect(rtlScreen.getAllByRole('term')).toHaveLength(items.length);
expect(rtlScreen.getAllByRole('definition')).toHaveLength(items.length);
});
it('can render a centered list of meta items', () => {
- const items: MetaItemData[] = [
+ const items = [
{ id: 'item1', label: 'Item 1', value: 'Value 1' },
{ id: 'item2', label: 'Item 2', value: 'Value 2' },
{ id: 'item3', label: 'Item 3', value: 'Value 3' },
{ id: 'item4', label: 'Item 4', value: 'Value 4' },
];
- render(<MetaList isCentered items={items} />);
+ render(
+ <MetaList isCentered>
+ {items.map(({ id, ...item }) => (
+ <MetaItem key={id} {...item} />
+ ))}
+ </MetaList>
+ );
const terms = rtlScreen.getAllByRole('term');
@@ -33,47 +46,23 @@ describe('MetaList', () => {
});
it('can render an inlined list of meta items', () => {
- const items: MetaItemData[] = [
+ const items = [
{ id: 'item1', label: 'Item 1', value: 'Value 1' },
{ id: 'item2', label: 'Item 2', value: 'Value 2' },
{ id: 'item3', label: 'Item 3', value: 'Value 3' },
{ id: 'item4', label: 'Item 4', value: 'Value 4' },
];
- render(<MetaList isInline items={items} />);
+ render(
+ <MetaList isInline>
+ {items.map(({ id, ...item }) => (
+ <MetaItem key={id} {...item} />
+ ))}
+ </MetaList>
+ );
const terms = rtlScreen.getAllByRole('term');
expect(terms[0].parentElement?.parentElement).toHaveClass('list--inlined');
});
-
- it('can render a list of meta items with bordered values', () => {
- const items: MetaItemData[] = [
- { id: 'item1', label: 'Item 1', value: 'Value 1' },
- { id: 'item2', label: 'Item 2', value: 'Value 2' },
- { id: 'item3', label: 'Item 3', value: 'Value 3' },
- { id: 'item4', label: 'Item 4', value: 'Value 4' },
- ];
-
- render(<MetaList hasBorderedValues items={items} />);
-
- const terms = rtlScreen.getAllByRole('term');
-
- expect(terms[0].parentElement).toHaveClass('item--bordered-values');
- });
-
- it('can render a list of meta items with inlined values', () => {
- const items: MetaItemData[] = [
- { id: 'item1', label: 'Item 1', value: 'Value 1' },
- { id: 'item2', label: 'Item 2', value: 'Value 2' },
- { id: 'item3', label: 'Item 3', value: 'Value 3' },
- { id: 'item4', label: 'Item 4', value: 'Value 4' },
- ];
-
- render(<MetaList hasInlinedValues items={items} />);
-
- const terms = rtlScreen.getAllByRole('term');
-
- expect(terms[0].parentElement).toHaveClass('item--inlined-values');
- });
});
diff --git a/src/components/molecules/meta-list/meta-list.tsx b/src/components/molecules/meta-list/meta-list.tsx
index 288fd9a..c19f0fd 100644
--- a/src/components/molecules/meta-list/meta-list.tsx
+++ b/src/components/molecules/meta-list/meta-list.tsx
@@ -1,54 +1,32 @@
-import { type ForwardRefRenderFunction, forwardRef } from 'react';
+import {
+ type ForwardRefRenderFunction,
+ forwardRef,
+ type ReactNode,
+} from 'react';
import { DescriptionList, type DescriptionListProps } from '../../atoms';
-import { MetaItem, type MetaItemProps } from './meta-item';
import styles from './meta-list.module.scss';
-export type MetaItemData = Pick<
- MetaItemProps,
- | 'hasBorderedValues'
- | 'hasInlinedValues'
- | 'isCentered'
- | 'isInline'
- | 'label'
- | 'value'
+export type MetaListProps = Omit<
+ DescriptionListProps,
+ 'children' | 'spacing'
> & {
- id: string;
+ /**
+ * The meta items.
+ */
+ children: ReactNode;
+ /**
+ * Should the meta be centered?
+ *
+ * @default false
+ */
+ isCentered?: boolean;
};
-export type MetaListProps = Omit<DescriptionListProps, 'children' | 'spacing'> &
- Pick<MetaItemProps, 'hasBorderedValues' | 'hasInlinedValues'> & {
- /**
- * Should the items be inlined?
- *
- * @default false
- */
- hasInlinedItems?: boolean;
- /**
- * Should the meta be centered?
- *
- * @default false
- */
- isCentered?: boolean;
- /**
- * The meta items.
- */
- items: MetaItemData[];
- };
-
const MetaListWithRef: ForwardRefRenderFunction<
HTMLDListElement,
MetaListProps
> = (
- {
- className = '',
- hasBorderedValues = false,
- hasInlinedItems = false,
- hasInlinedValues = false,
- isCentered = false,
- isInline = false,
- items,
- ...props
- },
+ { children, className = '', isCentered = false, isInline = false, ...props },
ref
) => {
const listClass = [
@@ -60,17 +38,7 @@ const MetaListWithRef: ForwardRefRenderFunction<
return (
<DescriptionList {...props} className={listClass} ref={ref}>
- {items.map(({ id, ...item }) => (
- <MetaItem
- hasBorderedValues={hasBorderedValues}
- hasInlinedValues={hasInlinedValues}
- isCentered={isCentered}
- isInline={hasInlinedItems}
- // Each item should be able to override the global settings.
- {...item}
- key={id}
- />
- ))}
+ {children}
</DescriptionList>
);
};
diff --git a/src/components/organisms/comment/approved-comment/approved-comment.tsx b/src/components/organisms/comment/approved-comment/approved-comment.tsx
index db5345b..233146d 100644
--- a/src/components/organisms/comment/approved-comment/approved-comment.tsx
+++ b/src/components/organisms/comment/approved-comment/approved-comment.tsx
@@ -12,6 +12,7 @@ import {
CardTitle,
CardFooter,
CardActions,
+ MetaItem,
} from '../../../molecules';
import styles from './approved-comment.module.scss';
@@ -138,20 +139,17 @@ const ApprovedCommentWithRef: ForwardRefRenderFunction<
author.name
)}
</CardTitle>
- <CardMeta
- hasInlinedItems
- items={[
- {
- id: 'publication-date',
- label: publicationDateLabel,
- value: (
- <Link href={commentLink}>
- <Time date={publicationDate} showTime />
- </Link>
- ),
- },
- ]}
- />
+ <CardMeta>
+ <MetaItem
+ isInline
+ label={publicationDateLabel}
+ value={
+ <Link href={commentLink}>
+ <Time date={publicationDate} showTime />
+ </Link>
+ }
+ />
+ </CardMeta>
</CardHeader>
<CardBody
className={styles.body}
diff --git a/src/components/organisms/post-preview/post-preview-meta/post-preview-meta.tsx b/src/components/organisms/post-preview/post-preview-meta/post-preview-meta.tsx
index 5a342da..54e359e 100644
--- a/src/components/organisms/post-preview/post-preview-meta/post-preview-meta.tsx
+++ b/src/components/organisms/post-preview/post-preview-meta/post-preview-meta.tsx
@@ -1,12 +1,13 @@
-import type { FC, ReactNode } from 'react';
+import type { FC, ReactElement, ReactNode } from 'react';
import { useIntl } from 'react-intl';
import type { PageLink } from '../../../../types';
import { getReadingTimeFrom } from '../../../../utils/helpers';
import { Link, Time, VisuallyHidden } from '../../../atoms';
import {
CardMeta,
- type MetaItemData,
type CardMetaProps,
+ MetaItem,
+ type MetaItemProps,
} from '../../../molecules';
const a11y = (chunks: ReactNode) => <VisuallyHidden>{chunks}</VisuallyHidden>;
@@ -57,20 +58,7 @@ export type PostPreviewMetaData = {
wordsCount?: number;
};
-const validMetaKeys = [
- 'author',
- 'comments',
- 'publicationDate',
- 'thematics',
- 'topics',
- 'updateDate',
- 'wordsCount',
-] satisfies (keyof PostPreviewMetaData)[];
-
-const isValidMetaKey = (key: string): key is keyof PostPreviewMetaData =>
- (validMetaKeys as string[]).includes(key);
-
-export type PostPreviewMetaProps = Omit<CardMetaProps, 'items'> & {
+export type PostPreviewMetaProps = Omit<CardMetaProps, 'children' | 'items'> & {
/**
* The post meta.
*/
@@ -83,23 +71,20 @@ export const PostPreviewMeta: FC<PostPreviewMetaProps> = ({
}) => {
const intl = useIntl();
- const getAuthor = (): MetaItemData | undefined => {
- if (!meta.author) return undefined;
-
- return {
- id: 'author',
- label: intl.formatMessage({
+ const getAuthor = (author: string): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage({
defaultMessage: 'Written by:',
description: 'PostPreviewMeta: author label',
id: '2U7ixo',
- }),
- value: meta.author,
- };
- };
-
- const getCommentsCount = (): MetaItemData | undefined => {
- if (!meta.comments) return undefined;
-
+ })}
+ value={author}
+ />
+ );
+
+ const getComments = (
+ comments: PostPreviewMetaComment
+ ): ReactElement<MetaItemProps> => {
const commentsLabel = intl.formatMessage<ReactNode>(
{
defaultMessage:
@@ -109,146 +94,121 @@ export const PostPreviewMeta: FC<PostPreviewMetaProps> = ({
},
{
a11y,
- commentsCount: meta.comments.count,
- title: meta.comments.postHeading,
+ commentsCount: comments.count,
+ title: comments.postHeading,
}
);
- return {
- id: 'comments',
- label: intl.formatMessage({
- defaultMessage: 'Comments:',
- description: 'PostPreviewMeta: comments label',
- id: 'FCpPCm',
- }),
- value: meta.comments.url ? (
- <Link href={meta.comments.url}>{commentsLabel}</Link>
- ) : (
- <>{commentsLabel}</>
- ),
- };
+ return (
+ <MetaItem
+ label={intl.formatMessage({
+ defaultMessage: 'Comments:',
+ description: 'PostPreviewMeta: comments label',
+ id: 'FCpPCm',
+ })}
+ value={
+ comments.url ? (
+ <Link href={comments.url}>{commentsLabel}</Link>
+ ) : (
+ <>{commentsLabel}</>
+ )
+ }
+ />
+ );
};
- const getPublicationDate = (): MetaItemData | undefined => {
- if (!meta.publicationDate) return undefined;
-
- return {
- id: 'publication-date',
- label: intl.formatMessage({
+ const getPublicationDate = (date: string): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage({
defaultMessage: 'Published on:',
description: 'PostPreviewMeta: publication date label',
id: '+6f4p1',
- }),
- value: <Time date={meta.publicationDate} />,
- };
- };
-
- const getThematics = (): MetaItemData | undefined => {
- if (!meta.thematics?.length) return undefined;
-
- return {
- id: 'thematics',
- label: intl.formatMessage(
+ })}
+ value={<Time date={date} />}
+ />
+ );
+
+ const getThematics = (thematics: PageLink[]): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage(
{
defaultMessage:
'{thematicsCount, plural, =0 {Thematics:} one {Thematic:} other {Thematics:}}',
description: 'PostPreviewMeta: thematics label',
id: '9MTBCG',
},
- { thematicsCount: meta.thematics.length }
- ),
- value: meta.thematics.map((thematic) => {
+ { thematicsCount: thematics.length }
+ )}
+ value={thematics.map((thematic) => {
return {
id: `thematic-${thematic.id}`,
value: <Link href={thematic.url}>{thematic.name}</Link>,
};
- }),
- };
- };
-
- const getTopics = (): MetaItemData | undefined => {
- if (!meta.topics?.length) return undefined;
+ })}
+ />
+ );
- return {
- id: 'topics',
- label: intl.formatMessage(
+ const getTopics = (topics: PageLink[]): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage(
{
defaultMessage:
'{topicsCount, plural, =0 {Topics:} one {Topic:} other {Topics:}}',
description: 'PostPreviewMeta: topics label',
id: 'aBQYbE',
},
- { topicsCount: meta.topics.length }
- ),
- value: meta.topics.map((topic) => {
+ { topicsCount: topics.length }
+ )}
+ value={topics.map((topic) => {
return {
id: `topic-${topic.id}`,
value: <Link href={topic.url}>{topic.name}</Link>,
};
- }),
- };
- };
+ })}
+ />
+ );
- const getUpdateDate = (): MetaItemData | undefined => {
- if (!meta.updateDate || meta.updateDate === meta.publicationDate)
- return undefined;
-
- return {
- id: 'update-date',
- label: intl.formatMessage({
+ const getUpdateDate = (date: string): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage({
defaultMessage: 'Updated on:',
description: 'PostPreviewMeta: update date label',
id: 'ZmRh0V',
- }),
- value: <Time date={meta.updateDate} />,
- };
- };
-
- const getReadingTime = (): MetaItemData | undefined => {
- if (!meta.wordsCount) return undefined;
-
- return {
- id: 'reading-time',
- label: intl.formatMessage({
+ })}
+ value={<Time date={date} />}
+ />
+ );
+
+ const getReadingTime = (wordsCount: number): ReactElement<MetaItemProps> => (
+ <MetaItem
+ label={intl.formatMessage({
defaultMessage: 'Reading time:',
description: 'PostPreviewMeta: reading time label',
id: 'B1lS/v',
- }),
- value: intl.formatMessage(
+ })}
+ value={intl.formatMessage(
{
defaultMessage:
'{minutesCount, plural, =0 {Less than one minute} one {# minute} other {# minutes}}',
description: 'PostPreviewMeta: rounded minutes count',
id: 'y+13Ax',
},
- { minutesCount: getReadingTimeFrom(meta.wordsCount).inMinutes() }
- ),
- };
- };
-
- const items: MetaItemData[] = Object.keys(meta)
- .filter(isValidMetaKey)
- .map((key): MetaItemData | undefined => {
- switch (key) {
- case 'author':
- return getAuthor();
- case 'comments':
- return getCommentsCount();
- case 'publicationDate':
- return getPublicationDate();
- case 'thematics':
- return getThematics();
- case 'topics':
- return getTopics();
- case 'updateDate':
- return getUpdateDate();
- case 'wordsCount':
- return getReadingTime();
- default:
- throw new Error('Unsupported meta key.');
- }
- })
- .filter((item): item is MetaItemData => item !== undefined);
-
- return <CardMeta {...props} items={items} />;
+ { minutesCount: getReadingTimeFrom(wordsCount).inMinutes() }
+ )}
+ />
+ );
+
+ return (
+ <CardMeta {...props}>
+ {meta.author ? getAuthor(meta.author) : null}
+ {meta.publicationDate ? getPublicationDate(meta.publicationDate) : null}
+ {meta.updateDate && meta.updateDate !== meta.publicationDate
+ ? getUpdateDate(meta.updateDate)
+ : null}
+ {meta.wordsCount ? getReadingTime(meta.wordsCount) : null}
+ {meta.thematics ? getThematics(meta.thematics) : null}
+ {meta.topics ? getTopics(meta.topics) : null}
+ {meta.comments ? getComments(meta.comments) : null}
+ </CardMeta>
+ );
};
diff --git a/src/components/organisms/project-overview/project-overview.tsx b/src/components/organisms/project-overview/project-overview.tsx
index 2b8be0e..f524120 100644
--- a/src/components/organisms/project-overview/project-overview.tsx
+++ b/src/components/organisms/project-overview/project-overview.tsx
@@ -6,7 +6,7 @@ import {
type ReactElement,
} from 'react';
import { useIntl } from 'react-intl';
-import type { Maybe, ValueOf } from '../../../types';
+import type { ValueOf } from '../../../types';
import {
Time,
type SocialWebsite,
@@ -14,7 +14,7 @@ import {
SocialLink,
Figure,
} from '../../atoms';
-import { MetaList, type MetaItemData } from '../../molecules';
+import { MetaItem, type MetaItemProps, MetaList } from '../../molecules';
import styles from './project-overview.module.scss';
export type Repository = {
@@ -155,27 +155,31 @@ const ProjectOverviewWithRef: ForwardRefRenderFunction<
[intl]
);
- const getMetaItems = useCallback((): MetaItemData[] => {
+ const getMetaItems = useCallback(() => {
const keys = Object.keys(meta).filter(isValidMetaKey);
return keys
- .map((key): Maybe<MetaItemData> => {
+ .map((key) => {
const value = meta[key];
- return value
- ? {
- id: key,
- label: metaLabels[key],
- value: getMetaValue(key, value),
- hasBorderedValues: key === 'technologies',
- hasInlinedValues:
- (key === 'technologies' || key === 'repositories') &&
- Array.isArray(value) &&
- value.length > 1,
+ return value ? (
+ <MetaItem
+ hasBorderedValues={key === 'technologies'}
+ hasInlinedValues={
+ (key === 'technologies' || key === 'repositories') &&
+ Array.isArray(value) &&
+ value.length > 1
}
- : undefined;
+ key={key}
+ label={metaLabels[key]}
+ value={getMetaValue(key, value)}
+ />
+ ) : undefined;
})
- .filter((item): item is MetaItemData => typeof item !== 'undefined');
+ .filter(
+ (item): item is ReactElement<MetaItemProps> =>
+ typeof item !== 'undefined'
+ );
}, [getMetaValue, meta, metaLabels]);
return (
@@ -185,7 +189,9 @@ const ProjectOverviewWithRef: ForwardRefRenderFunction<
{cover}
</Figure>
) : null}
- <MetaList className={styles.meta} isInline items={getMetaItems()} />
+ <MetaList className={styles.meta} isInline>
+ {getMetaItems()}
+ </MetaList>
</div>
);
};
diff --git a/src/components/templates/page/page-layout.stories.tsx b/src/components/templates/page/page-layout.stories.tsx
index 2b44933..6dcbeea 100644
--- a/src/components/templates/page/page-layout.stories.tsx
+++ b/src/components/templates/page/page-layout.stories.tsx
@@ -1,5 +1,6 @@
import type { ComponentMeta, ComponentStory } from '@storybook/react';
import { ButtonLink, Heading, Link } from '../../atoms';
+import { MetaItem, MetaList } from '../../molecules';
import { LinksWidget, PostsList, SharingWidget } from '../../organisms';
import { LayoutBase } from '../layout/layout.stories';
import { PageLayout as PageLayoutComponent } from './page-layout';
@@ -270,38 +271,41 @@ Post.args = {
breadcrumb: postBreadcrumb,
title: pageTitle,
intro: pageIntro,
- headerMeta: [
- { id: 'publication-date', label: 'Published on:', value: '2020-03-14' },
- {
- id: 'thematics',
- label: 'Thematics:',
- value: [
- {
- id: 'cat-1',
- value: (
- <Link key="cat1" href="#">
- Cat 1
- </Link>
- ),
- },
- {
- id: 'cat-2',
- value: (
- <Link key="cat2" href="#">
- Cat 2
- </Link>
- ),
- },
- ],
- },
- ],
- footerMeta: [
- {
- id: 'read-more',
- label: 'Read more about:',
- value: <ButtonLink to="#">Topic 1</ButtonLink>,
- },
- ],
+ headerMeta: (
+ <MetaList>
+ <MetaItem isInline label="Published on:" value="2020-03-14" />
+ <MetaItem
+ isInline
+ label="Thematic:"
+ value={[
+ {
+ id: 'cat-1',
+ value: (
+ <Link key="cat1" href="#">
+ Cat 1
+ </Link>
+ ),
+ },
+ {
+ id: 'cat-2',
+ value: (
+ <Link key="cat2" href="#">
+ Cat 2
+ </Link>
+ ),
+ },
+ ]}
+ />
+ </MetaList>
+ ),
+ footerMeta: (
+ <MetaList>
+ <MetaItem
+ label="Read more about:"
+ value={<ButtonLink to="#">Topic 1</ButtonLink>}
+ />
+ </MetaList>
+ ),
children: (
<>
<Heading level={2}>Impedit commodi rerum</Heading>
@@ -497,7 +501,11 @@ export const Blog = Template.bind({});
Blog.args = {
breadcrumb: postsListBreadcrumb,
title: 'Blog',
- headerMeta: [{ id: 'total', label: 'Total:', value: `${posts.length}` }],
+ headerMeta: (
+ <MetaList>
+ <MetaItem isInline label="Total:" value={`${posts.length}`} />
+ </MetaList>
+ ),
children: <PostsList posts={posts} sortByYear />,
widgets: [
<LinksWidget
diff --git a/src/components/templates/page/page-layout.tsx b/src/components/templates/page/page-layout.tsx
index db71e07..75d308e 100644
--- a/src/components/templates/page/page-layout.tsx
+++ b/src/components/templates/page/page-layout.tsx
@@ -12,12 +12,7 @@ import { sendComment } from '../../../services/graphql';
import type { SendCommentInput } from '../../../types';
import { useHeadingsTree } from '../../../utils/hooks';
import { Heading, Sidebar } from '../../atoms';
-import {
- PageFooter,
- type PageFooterProps,
- PageHeader,
- type PageHeaderProps,
-} from '../../molecules';
+import { PageFooter, PageHeader, type PageHeaderProps } from '../../molecules';
import {
CommentForm,
CommentsList,
@@ -61,11 +56,11 @@ export type PageLayoutProps = {
/**
* The footer metadata.
*/
- footerMeta?: PageFooterProps['meta'];
+ footerMeta?: ReactNode;
/**
* The header metadata.
*/
- headerMeta?: PageHeaderProps['meta'];
+ headerMeta?: ReactNode;
/**
* The page id.
*/
@@ -240,8 +235,8 @@ export const PageLayout: FC<PageLayoutProps> = ({
{children}
</div>
)}
- {footerMeta?.length ? (
- <PageFooter meta={footerMeta} className={styles.footer} />
+ {footerMeta ? (
+ <PageFooter className={styles.footer}>{footerMeta}</PageFooter>
) : null}
<Sidebar
aria-label={intl.formatMessage({
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 008f476..2091057 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -59,10 +59,6 @@
"defaultMessage": "Name:",
"description": "ContactForm: name label"
},
- "24FIsG": {
- "defaultMessage": "Updated on:",
- "description": "ThematicPage: update date label"
- },
"28GZdv": {
"defaultMessage": "Projects",
"description": "Breadcrumb: projects label"
@@ -155,10 +151,6 @@
"defaultMessage": "{date} at {time}",
"description": "Time: readable date and time"
},
- "9DfuHk": {
- "defaultMessage": "Updated on:",
- "description": "TopicPage: update date label"
- },
"9MTBCG": {
"defaultMessage": "{thematicsCount, plural, =0 {Thematics:} one {Thematic:} other {Thematics:}}",
"description": "PostPreviewMeta: thematics label"
@@ -291,10 +283,6 @@
"defaultMessage": "Thematics",
"description": "BlogPage: thematics list widget title"
},
- "HxZvY4": {
- "defaultMessage": "Published on:",
- "description": "ProjectsPage: publication date label"
- },
"IVczxR": {
"defaultMessage": "Go to page {number}",
"description": "BlogPage: page number label"
@@ -323,10 +311,6 @@
"defaultMessage": "Skip to content",
"description": "Layout: Skip to content link"
},
- "KV+NMZ": {
- "defaultMessage": "Published on:",
- "description": "TopicPage: publication date label"
- },
"KVSWGP": {
"defaultMessage": "Other thematics",
"description": "ThematicPage: other thematics list widget title"
@@ -427,10 +411,6 @@
"defaultMessage": "CV",
"description": "Layout: main nav - cv link"
},
- "RecdwX": {
- "defaultMessage": "Published on:",
- "description": "ArticlePage: publication date label"
- },
"RvGb2c": {
"defaultMessage": "{postsCount, plural, =0 {No articles} one {# article} other {# articles}}",
"description": "Page: posts count meta"
@@ -451,10 +431,6 @@
"defaultMessage": "An error occurred:",
"description": "Contact: error message"
},
- "UTGhUU": {
- "defaultMessage": "Published on:",
- "description": "ThematicPage: publication date label"
- },
"VkAnvv": {
"defaultMessage": "Send",
"description": "ContactForm: send button"
@@ -499,10 +475,6 @@
"defaultMessage": "Light theme",
"description": "ThemeToggle: light theme label"
},
- "ZAqGZ6": {
- "defaultMessage": "Updated on:",
- "description": "ArticlePage: update date label"
- },
"ZB/Aw2": {
"defaultMessage": "Partial includes only page url, views and duration.",
"description": "AckeeToggle: tooltip message"
@@ -719,10 +691,6 @@
"defaultMessage": "Theme:",
"description": "ThemeToggle: theme label"
},
- "tBX4mb": {
- "defaultMessage": "Total:",
- "description": "TopicPage: total label"
- },
"tIZYpD": {
"defaultMessage": "Partial",
"description": "AckeeToggle: partial option name"
@@ -739,10 +707,6 @@
"defaultMessage": "Website:",
"description": "CommentForm: website label"
},
- "uAL4iW": {
- "defaultMessage": "{postsCount, plural, =0 {No articles} one {# article} other {# articles}}",
- "description": "TopicPage: posts count meta"
- },
"uZj4QI": {
"defaultMessage": "Cancel reply",
"description": "CommentsList: cancel reply button"
@@ -767,10 +731,6 @@
"defaultMessage": "Free",
"description": "HomePage: link to free thematic"
},
- "wQrvgw": {
- "defaultMessage": "Updated on:",
- "description": "ProjectsPage: update date label"
- },
"xaqaYQ": {
"defaultMessage": "Sending mail...",
"description": "ContactForm: spinner message on submit"
diff --git a/src/i18n/fr.json b/src/i18n/fr.json
index c83d146..d6bdef1 100644
--- a/src/i18n/fr.json
+++ b/src/i18n/fr.json
@@ -59,10 +59,6 @@
"defaultMessage": "Nom :",
"description": "ContactForm: name label"
},
- "24FIsG": {
- "defaultMessage": "Mis à jour le :",
- "description": "ThematicPage: update date label"
- },
"28GZdv": {
"defaultMessage": "Projets",
"description": "Breadcrumb: projects label"
@@ -155,10 +151,6 @@
"defaultMessage": "{date} à {time}",
"description": "Time: readable date and time"
},
- "9DfuHk": {
- "defaultMessage": "Mis à jour le :",
- "description": "TopicPage: update date label"
- },
"9MTBCG": {
"defaultMessage": "{thematicsCount, plural, =0 {Thématiques :} one {Thématique :} other {Thématiques :}}",
"description": "PostPreviewMeta: thematics label"
@@ -291,10 +283,6 @@
"defaultMessage": "Thématiques",
"description": "BlogPage: thematics list widget title"
},
- "HxZvY4": {
- "defaultMessage": "Publié le :",
- "description": "ProjectsPage: publication date label"
- },
"IVczxR": {
"defaultMessage": "Aller à la page {number}",
"description": "BlogPage: page number label"
@@ -323,10 +311,6 @@
"defaultMessage": "Aller au contenu",
"description": "Layout: Skip to content link"
},
- "KV+NMZ": {
- "defaultMessage": "Publié le :",
- "description": "TopicPage: publication date label"
- },
"KVSWGP": {
"defaultMessage": "Autres thématiques",
"description": "ThematicPage: other thematics list widget title"
@@ -427,10 +411,6 @@
"defaultMessage": "CV",
"description": "Layout: main nav - cv link"
},
- "RecdwX": {
- "defaultMessage": "Publié le :",
- "description": "ArticlePage: publication date label"
- },
"RvGb2c": {
"defaultMessage": "{postsCount, plural, =0 {0 article} one {# article} other {# articles}}",
"description": "Page: posts count meta"
@@ -451,10 +431,6 @@
"defaultMessage": "Une erreur est survenue :",
"description": "Contact: error message"
},
- "UTGhUU": {
- "defaultMessage": "Publié le :",
- "description": "ThematicPage: publication date label"
- },
"VkAnvv": {
"defaultMessage": "Envoyer",
"description": "ContactForm: send button"
@@ -499,10 +475,6 @@
"defaultMessage": "Thème clair",
"description": "ThemeToggle: light theme label"
},
- "ZAqGZ6": {
- "defaultMessage": "Mis à jour le :",
- "description": "ArticlePage: update date label"
- },
"ZB/Aw2": {
"defaultMessage": "Partiel inclut seulement l’url de la page, le nombre de visites et la durée.",
"description": "AckeeToggle: tooltip message"
@@ -719,10 +691,6 @@
"defaultMessage": "Thème :",
"description": "ThemeToggle: theme label"
},
- "tBX4mb": {
- "defaultMessage": "Total :",
- "description": "TopicPage: total label"
- },
"tIZYpD": {
"defaultMessage": "Partiel",
"description": "AckeeToggle: partial option name"
@@ -739,10 +707,6 @@
"defaultMessage": "Site web :",
"description": "CommentForm: website label"
},
- "uAL4iW": {
- "defaultMessage": "{postsCount, plural, =0 {0 article} one {# article} other {# articles}}",
- "description": "TopicPage: posts count meta"
- },
"uZj4QI": {
"defaultMessage": "Annuler la réponse",
"description": "CommentsList: cancel reply button"
@@ -767,10 +731,6 @@
"defaultMessage": "Libre",
"description": "HomePage: link to free thematic"
},
- "wQrvgw": {
- "defaultMessage": "Mis à jour le :",
- "description": "ProjectsPage: update date label"
- },
"xaqaYQ": {
"defaultMessage": "Mail en cours d’envoi…",
"description": "ContactForm: spinner message on submit"
diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx
index 7875d1d..0cba7a6 100644
--- a/src/pages/article/[slug].tsx
+++ b/src/pages/article/[slug].tsx
@@ -15,10 +15,11 @@ import {
PageLayout,
SharingWidget,
Spinner,
- type MetaItemData,
Time,
type CommentData,
Heading,
+ MetaList,
+ MetaItem,
} from '../../components';
import {
getAllArticlesSlugs,
@@ -112,102 +113,6 @@ const ArticlePage: NextPageWithLayout<ArticlePageProps> = ({
const { content, id, intro, meta, title } = article;
const { author, commentsCount, cover, dates, seo, thematics, topics } = meta;
- const headerMeta: (MetaItemData | undefined)[] = [
- author
- ? {
- id: 'author',
- label: intl.formatMessage({
- defaultMessage: 'Written by:',
- description: 'ArticlePage: author label',
- id: 'MJbZfX',
- }),
- value: author.name,
- }
- : undefined,
- {
- id: 'publication-date',
- label: intl.formatMessage({
- defaultMessage: 'Published on:',
- description: 'ArticlePage: publication date label',
- id: 'RecdwX',
- }),
- value: <Time date={dates.publication} />,
- },
- dates.update && dates.publication !== dates.update
- ? {
- id: 'update-date',
- label: intl.formatMessage({
- defaultMessage: 'Updated on:',
- description: 'ArticlePage: update date label',
- id: 'ZAqGZ6',
- }),
- value: <Time date={dates.update} />,
- }
- : undefined,
- {
- id: 'reading-time',
- label: intl.formatMessage({
- defaultMessage: 'Reading time:',
- description: 'ArticlePage: reading time label',
- id: 'Gw7X3x',
- }),
- value: readingTime,
- },
- thematics
- ? {
- id: 'thematics',
- label: intl.formatMessage({
- defaultMessage: 'Thematics:',
- description: 'ArticlePage: thematics meta label',
- id: 'CvOqoh',
- }),
- value: thematics.map((thematic) => {
- return {
- id: `thematic-${thematic.id}`,
- value: (
- <Link key={thematic.id} href={thematic.url}>
- {thematic.name}
- </Link>
- ),
- };
- }),
- }
- : undefined,
- ];
- const filteredHeaderMeta = headerMeta.filter(
- (item): item is MetaItemData => !!item
- );
-
- const footerMetaLabel = intl.formatMessage({
- defaultMessage: 'Read more articles about:',
- description: 'ArticlePage: footer topics list label',
- id: '50xc4o',
- });
-
- const footerMeta: MetaItemData[] = topics
- ? [
- {
- id: 'more-about',
- label: footerMetaLabel,
- value: topics.map((topic) => {
- return {
- id: `topic--${topic.id}`,
- value: (
- <ButtonLink
- className={styles.btn}
- key={topic.id}
- to={topic.url}
- >
- {topic.logo ? <NextImage {...topic.logo} /> : null}{' '}
- {topic.name}
- </ButtonLink>
- ),
- };
- }),
- },
- ]
- : [];
-
const webpageSchema = getWebPageSchema({
description: intro,
locale: CONFIG.locales.defaultLocale,
@@ -333,8 +238,99 @@ const ArticlePage: NextPageWithLayout<ArticlePageProps> = ({
breadcrumb={breadcrumbItems}
breadcrumbSchema={breadcrumbSchema}
comments={getComments(commentsData)}
- footerMeta={footerMeta}
- headerMeta={filteredHeaderMeta}
+ footerMeta={
+ topics ? (
+ <MetaList>
+ <MetaItem
+ hasInlinedValues
+ label={intl.formatMessage({
+ defaultMessage: 'Read more articles about:',
+ description: 'ArticlePage: footer topics list label',
+ id: '50xc4o',
+ })}
+ value={topics.map((topic) => {
+ return {
+ id: `topic--${topic.id}`,
+ value: (
+ <ButtonLink
+ className={styles.btn}
+ key={topic.id}
+ to={topic.url}
+ >
+ {topic.logo ? <NextImage {...topic.logo} /> : null}{' '}
+ {topic.name}
+ </ButtonLink>
+ ),
+ };
+ })}
+ />
+ </MetaList>
+ ) : undefined
+ }
+ headerMeta={
+ <MetaList>
+ {author ? (
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Written by:',
+ description: 'ArticlePage: author label',
+ id: 'MJbZfX',
+ })}
+ value={author.name}
+ />
+ ) : null}
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Published on:',
+ description: 'Page: publication date label',
+ id: '4QbTDq',
+ })}
+ value={<Time date={dates.publication} />}
+ />
+ {dates.update ? (
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Updated on:',
+ description: 'Page: update date label',
+ id: 'Ez8Qim',
+ })}
+ value={<Time date={dates.update} />}
+ />
+ ) : null}
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Reading time:',
+ description: 'ArticlePage: reading time label',
+ id: 'Gw7X3x',
+ })}
+ value={readingTime}
+ />
+ {thematics ? (
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Thematics:',
+ description: 'ArticlePage: thematics meta label',
+ id: 'CvOqoh',
+ })}
+ value={thematics.map((thematic) => {
+ return {
+ id: `thematic-${thematic.id}`,
+ value: (
+ <Link key={thematic.id} href={thematic.url}>
+ {thematic.name}
+ </Link>
+ ),
+ };
+ })}
+ />
+ ) : null}
+ </MetaList>
+ }
id={id as number}
intro={intro}
title={title}
diff --git a/src/pages/blog/index.tsx b/src/pages/blog/index.tsx
index 5a13e3e..6ed6eda 100644
--- a/src/pages/blog/index.tsx
+++ b/src/pages/blog/index.tsx
@@ -9,13 +9,14 @@ import {
getLayout,
Heading,
LinksWidget,
- type MetaItemData,
Notice,
PageLayout,
PostsList,
Pagination,
type RenderPaginationLink,
type RenderPaginationItemAriaLabel,
+ MetaList,
+ MetaItem,
} from '../../components';
import {
getArticles,
@@ -183,28 +184,6 @@ const BlogPage: NextPageWithLayout<BlogPageProps> = ({
[intl]
);
- const headerMeta: MetaItemData[] = totalArticles
- ? [
- {
- id: 'posts-count',
- label: intl.formatMessage({
- defaultMessage: 'Total:',
- description: 'Page: total label',
- id: 'kNBXyK',
- }),
- value: intl.formatMessage(
- {
- defaultMessage:
- '{postsCount, plural, =0 {No articles} one {# article} other {# articles}}',
- description: 'Page: posts count meta',
- id: 'RvGb2c',
- },
- { postsCount: totalArticles }
- ),
- },
- ]
- : [];
-
const paginationAriaLabel = intl.formatMessage({
defaultMessage: 'Pagination',
description: 'BlogPage: pagination accessible name',
@@ -234,7 +213,27 @@ const BlogPage: NextPageWithLayout<BlogPageProps> = ({
title={title}
breadcrumb={breadcrumbItems}
breadcrumbSchema={breadcrumbSchema}
- headerMeta={headerMeta}
+ headerMeta={
+ <MetaList>
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Total:',
+ description: 'Page: total label',
+ id: 'kNBXyK',
+ })}
+ value={intl.formatMessage(
+ {
+ defaultMessage:
+ '{postsCount, plural, =0 {No articles} one {# article} other {# articles}}',
+ description: 'Page: posts count meta',
+ id: 'RvGb2c',
+ },
+ { postsCount: totalArticles }
+ )}
+ />
+ </MetaList>
+ }
widgets={[
<LinksWidget
heading={
diff --git a/src/pages/blog/page/[number].tsx b/src/pages/blog/page/[number].tsx
index 03b641b..27d1816 100644
--- a/src/pages/blog/page/[number].tsx
+++ b/src/pages/blog/page/[number].tsx
@@ -10,12 +10,13 @@ import {
getLayout,
Heading,
LinksWidget,
- type MetaItemData,
PageLayout,
PostsList,
Pagination,
type RenderPaginationLink,
type RenderPaginationItemAriaLabel,
+ MetaList,
+ MetaItem,
} from '../../../components';
import {
getArticles,
@@ -187,28 +188,6 @@ const BlogPage: NextPageWithLayout<BlogPageProps> = ({
[intl]
);
- const headerMeta: MetaItemData[] = totalArticles
- ? [
- {
- id: 'posts-count',
- label: intl.formatMessage({
- defaultMessage: 'Total:',
- description: 'Page: total label',
- id: 'kNBXyK',
- }),
- value: intl.formatMessage(
- {
- defaultMessage:
- '{postsCount, plural, =0 {No articles} one {# article} other {# articles}}',
- description: 'Page: posts count meta',
- id: 'RvGb2c',
- },
- { postsCount: totalArticles }
- ),
- },
- ]
- : [];
-
const paginationAriaLabel = intl.formatMessage({
defaultMessage: 'Pagination',
description: 'BlogPage: pagination accessible name',
@@ -238,7 +217,27 @@ const BlogPage: NextPageWithLayout<BlogPageProps> = ({
title={pageTitleWithPageNumber}
breadcrumb={breadcrumbItems}
breadcrumbSchema={breadcrumbSchema}
- headerMeta={headerMeta}
+ headerMeta={
+ <MetaList>
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Total:',
+ description: 'Page: total label',
+ id: 'kNBXyK',
+ })}
+ value={intl.formatMessage(
+ {
+ defaultMessage:
+ '{postsCount, plural, =0 {No articles} one {# article} other {# articles}}',
+ description: 'Page: posts count meta',
+ id: 'RvGb2c',
+ },
+ { postsCount: totalArticles }
+ )}
+ />
+ </MetaList>
+ }
widgets={[
<LinksWidget
heading={
diff --git a/src/pages/cv.tsx b/src/pages/cv.tsx
index 5157249..0cda194 100644
--- a/src/pages/cv.tsx
+++ b/src/pages/cv.tsx
@@ -20,8 +20,9 @@ import {
PageLayout,
SocialMediaWidget,
ListItem,
- type MetaItemData,
Time,
+ MetaList,
+ MetaItem,
} from '../components';
import CVContent, { data, meta } from '../content/pages/cv.mdx';
import type { NextPageWithLayout } from '../types';
@@ -154,32 +155,6 @@ const CVPage: NextPageWithLayout = () => {
id: '+Dre5J',
});
- const headerMeta: (MetaItemData | undefined)[] = [
- {
- id: 'publication-date',
- label: intl.formatMessage({
- defaultMessage: 'Published on:',
- description: 'Page: publication date label',
- id: '4QbTDq',
- }),
- value: <Time date={dates.publication} />,
- },
- dates.update
- ? {
- id: 'update-date',
- label: intl.formatMessage({
- defaultMessage: 'Updated on:',
- description: 'Page: update date label',
- id: 'Ez8Qim',
- }),
- value: <Time date={dates.update} />,
- }
- : undefined,
- ];
- const filteredMeta = headerMeta.filter(
- (item): item is MetaItemData => !!item
- );
-
const cvCaption = intl.formatMessage(
{
defaultMessage: '<link>Download the CV in PDF</link>',
@@ -282,7 +257,30 @@ const CVPage: NextPageWithLayout = () => {
<PageLayout
breadcrumb={breadcrumbItems}
breadcrumbSchema={breadcrumbSchema}
- headerMeta={filteredMeta}
+ headerMeta={
+ <MetaList>
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Published on:',
+ description: 'Page: publication date label',
+ id: '4QbTDq',
+ })}
+ value={<Time date={dates.publication} />}
+ />
+ {dates.update ? (
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Updated on:',
+ description: 'Page: update date label',
+ id: 'Ez8Qim',
+ })}
+ value={<Time date={dates.update} />}
+ />
+ ) : null}
+ </MetaList>
+ }
intro={intro}
title={title}
widgets={widgets}
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index 0306736..d708ac5 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -25,6 +25,7 @@ import {
Section,
type SectionProps,
Time,
+ MetaItem,
} from '../components';
import HomePageContent from '../content/pages/homepage.mdx';
import { getArticlesCard } from '../services/graphql';
@@ -332,18 +333,14 @@ const HomePage: NextPageWithLayout<HomeProps> = ({ recentPosts }) => {
) : undefined
}
meta={
- <CardMeta
- hasBorderedValues
- hasInlinedValues
- isCentered
- items={[
- {
- id: 'publication-date',
- label: publicationDate,
- value: <Time date={post.dates.publication} />,
- },
- ]}
- />
+ <CardMeta isCentered>
+ <MetaItem
+ hasBorderedValues
+ isCentered
+ label={publicationDate}
+ value={<Time date={post.dates.publication} />}
+ />
+ </CardMeta>
}
isCentered
linkTo={`${ROUTES.ARTICLE}/${post.slug}`}
diff --git a/src/pages/mentions-legales.tsx b/src/pages/mentions-legales.tsx
index 50f60f5..e07263f 100644
--- a/src/pages/mentions-legales.tsx
+++ b/src/pages/mentions-legales.tsx
@@ -11,8 +11,9 @@ import {
Link,
PageLayout,
Figure,
- type MetaItemData,
Time,
+ MetaList,
+ MetaItem,
} from '../components';
import LegalNoticeContent, { meta } from '../content/pages/legal-notice.mdx';
import type { NextPageWithLayout } from '../types';
@@ -48,32 +49,6 @@ const LegalNoticePage: NextPageWithLayout = () => {
url: ROUTES.LEGAL_NOTICE,
});
- const headerMeta: (MetaItemData | undefined)[] = [
- {
- id: 'publication-date',
- label: intl.formatMessage({
- defaultMessage: 'Published on:',
- description: 'Page: publication date label',
- id: '4QbTDq',
- }),
- value: <Time date={dates.publication} />,
- },
- dates.update
- ? {
- id: 'update-date',
- label: intl.formatMessage({
- defaultMessage: 'Updated on:',
- description: 'Page: update date label',
- id: 'Ez8Qim',
- }),
- value: <Time date={dates.update} />,
- }
- : undefined,
- ];
- const filteredMeta = headerMeta.filter(
- (item): item is MetaItemData => !!item
- );
-
const { asPath } = useRouter();
const webpageSchema = getWebPageSchema({
description: seo.description,
@@ -101,7 +76,30 @@ const LegalNoticePage: NextPageWithLayout = () => {
<PageLayout
breadcrumb={breadcrumbItems}
breadcrumbSchema={breadcrumbSchema}
- headerMeta={filteredMeta}
+ headerMeta={
+ <MetaList>
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Published on:',
+ description: 'Page: publication date label',
+ id: '4QbTDq',
+ })}
+ value={<Time date={dates.publication} />}
+ />
+ {dates.update ? (
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Updated on:',
+ description: 'Page: update date label',
+ id: 'Ez8Qim',
+ })}
+ value={<Time date={dates.update} />}
+ />
+ ) : null}
+ </MetaList>
+ }
intro={intro}
title={title}
withToC={true}
diff --git a/src/pages/projets/[slug].tsx b/src/pages/projets/[slug].tsx
index 1aa9e7f..a8a4fea 100644
--- a/src/pages/projets/[slug].tsx
+++ b/src/pages/projets/[slug].tsx
@@ -19,12 +19,13 @@ import {
List,
ListItem,
Figure,
- type MetaItemData,
Time,
Grid,
ProjectOverview,
type ProjectMeta,
type Repository,
+ MetaList,
+ MetaItem,
} from '../../components';
import styles from '../../styles/pages/project.module.scss';
import type { NextPageWithLayout, ProjectPreview, Repos } from '../../types';
@@ -177,32 +178,6 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => {
url: `${CONFIG.url}${asPath}`,
};
- const headerMeta: (MetaItemData | undefined)[] = [
- {
- id: 'publication-date',
- label: intl.formatMessage({
- defaultMessage: 'Published on:',
- description: 'ProjectsPage: publication date label',
- id: 'HxZvY4',
- }),
- value: <Time date={dates.publication} />,
- },
- dates.update && dates.update !== dates.publication
- ? {
- id: 'update-date',
- label: intl.formatMessage({
- defaultMessage: 'Updated on:',
- description: 'ProjectsPage: update date label',
- id: 'wQrvgw',
- }),
- value: <Time date={dates.update} />,
- }
- : undefined,
- ];
- const filteredHeaderMeta = headerMeta.filter(
- (item): item is MetaItemData => !!item
- );
-
/**
* Retrieve the project repositories.
*
@@ -319,7 +294,30 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => {
intro={intro}
breadcrumb={breadcrumbItems}
breadcrumbSchema={breadcrumbSchema}
- headerMeta={filteredHeaderMeta}
+ headerMeta={
+ <MetaList>
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Published on:',
+ description: 'Page: publication date label',
+ id: '4QbTDq',
+ })}
+ value={<Time date={dates.publication} />}
+ />
+ {dates.update ? (
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Updated on:',
+ description: 'Page: update date label',
+ id: 'Ez8Qim',
+ })}
+ value={<Time date={dates.update} />}
+ />
+ ) : null}
+ </MetaList>
+ }
withToC={true}
widgets={[
<SharingWidget
diff --git a/src/pages/projets/index.tsx b/src/pages/projets/index.tsx
index 97b43e3..8feb701 100644
--- a/src/pages/projets/index.tsx
+++ b/src/pages/projets/index.tsx
@@ -19,6 +19,7 @@ import {
Link,
MetaList,
PageLayout,
+ MetaItem,
} from '../../components';
import PageContent, { meta } from '../../content/pages/projects.mdx';
import styles from '../../styles/pages/projects.module.scss';
@@ -86,20 +87,17 @@ const ProjectsPage: NextPageWithLayout<ProjectsPageProps> = ({ projects }) => {
}
meta={
technologies ? (
- <MetaList
- hasBorderedValues
- hasInlinedValues
- isCentered
- items={[
- {
- id: 'technologies',
- label: metaLabel,
- value: technologies.map((techno) => {
- return { id: techno, value: techno };
- }),
- },
- ]}
- />
+ <MetaList isCentered>
+ <MetaItem
+ hasBorderedValues
+ hasInlinedValues
+ isCentered
+ label={metaLabel}
+ value={technologies.map((techno) => {
+ return { id: techno, value: techno };
+ })}
+ />
+ </MetaList>
) : undefined
}
isCentered
diff --git a/src/pages/recherche/index.tsx b/src/pages/recherche/index.tsx
index 92035b0..0fb279b 100644
--- a/src/pages/recherche/index.tsx
+++ b/src/pages/recherche/index.tsx
@@ -9,13 +9,14 @@ import {
getLayout,
Heading,
LinksWidget,
- type MetaItemData,
Notice,
PageLayout,
PostsList,
Spinner,
SearchForm,
type SearchFormSubmit,
+ MetaList,
+ MetaItem,
} from '../../components';
import {
getArticles,
@@ -132,28 +133,6 @@ const SearchPage: NextPageWithLayout<SearchPageProps> = ({
getTotalArticles(query.s as string)
);
- const headerMeta: MetaItemData[] = totalArticles
- ? [
- {
- id: 'posts-count',
- label: intl.formatMessage({
- defaultMessage: 'Total:',
- description: 'Page: total label',
- id: 'kNBXyK',
- }),
- value: intl.formatMessage(
- {
- defaultMessage:
- '{postsCount, plural, =0 {No articles} one {# article} other {# articles}}',
- description: 'Page: posts count meta',
- id: 'RvGb2c',
- },
- { postsCount: totalArticles }
- ),
- },
- ]
- : [];
-
const thematicsListTitle = intl.formatMessage({
defaultMessage: 'Thematics',
description: 'SearchPage: thematics list widget title',
@@ -215,7 +194,27 @@ const SearchPage: NextPageWithLayout<SearchPageProps> = ({
title={title}
breadcrumb={breadcrumbItems}
breadcrumbSchema={breadcrumbSchema}
- headerMeta={headerMeta}
+ headerMeta={
+ <MetaList>
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Total:',
+ description: 'Page: total label',
+ id: 'kNBXyK',
+ })}
+ value={intl.formatMessage(
+ {
+ defaultMessage:
+ '{postsCount, plural, =0 {No articles} one {# article} other {# articles}}',
+ description: 'Page: posts count meta',
+ id: 'RvGb2c',
+ },
+ { postsCount: totalArticles }
+ )}
+ />
+ </MetaList>
+ }
widgets={[
<LinksWidget
heading={
diff --git a/src/pages/sujet/[slug].tsx b/src/pages/sujet/[slug].tsx
index a475df9..d9734a3 100644
--- a/src/pages/sujet/[slug].tsx
+++ b/src/pages/sujet/[slug].tsx
@@ -10,10 +10,11 @@ import {
getLayout,
Heading,
LinksWidget,
- type MetaItemData,
PageLayout,
PostsList,
Time,
+ MetaList,
+ MetaItem,
} from '../../components';
import {
getAllTopicsSlugs,
@@ -61,62 +62,6 @@ const TopicPage: NextPageWithLayout<TopicPageProps> = ({
url: `${ROUTES.TOPICS}/${slug}`,
});
- const headerMeta: (MetaItemData | undefined)[] = [
- {
- id: 'publication-date',
- label: intl.formatMessage({
- defaultMessage: 'Published on:',
- description: 'TopicPage: publication date label',
- id: 'KV+NMZ',
- }),
- value: <Time date={dates.publication} />,
- },
- dates.update
- ? {
- id: 'update-date',
- label: intl.formatMessage({
- defaultMessage: 'Updated on:',
- description: 'TopicPage: update date label',
- id: '9DfuHk',
- }),
- value: <Time date={dates.update} />,
- }
- : undefined,
- officialWebsite
- ? {
- id: 'website',
- label: intl.formatMessage({
- defaultMessage: 'Official website:',
- description: 'TopicPage: official website label',
- id: 'zoifQd',
- }),
- value: officialWebsite,
- }
- : undefined,
- articles?.length
- ? {
- id: 'total',
- label: intl.formatMessage({
- defaultMessage: 'Total:',
- description: 'TopicPage: total label',
- id: 'tBX4mb',
- }),
- value: intl.formatMessage(
- {
- defaultMessage:
- '{postsCount, plural, =0 {No articles} one {# article} other {# articles}}',
- description: 'TopicPage: posts count meta',
- id: 'uAL4iW',
- },
- { postsCount: articles.length }
- ),
- }
- : undefined,
- ];
- const filteredMeta = headerMeta.filter(
- (item): item is MetaItemData => !!item
- );
-
const { asPath } = useRouter();
const webpageSchema = getWebPageSchema({
description: seo.description,
@@ -181,7 +126,60 @@ const TopicPage: NextPageWithLayout<TopicPageProps> = ({
breadcrumbSchema={breadcrumbSchema}
title={getPageHeading()}
intro={intro}
- headerMeta={filteredMeta}
+ headerMeta={
+ <MetaList>
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Published on:',
+ description: 'Page: publication date label',
+ id: '4QbTDq',
+ })}
+ value={<Time date={dates.publication} />}
+ />
+ {dates.update ? (
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Updated on:',
+ description: 'Page: update date label',
+ id: 'Ez8Qim',
+ })}
+ value={<Time date={dates.update} />}
+ />
+ ) : null}
+ {officialWebsite ? (
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Official website:',
+ description: 'TopicPage: official website label',
+ id: 'zoifQd',
+ })}
+ value={officialWebsite}
+ />
+ ) : null}
+ {articles ? (
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Total:',
+ description: 'ThematicPage: total label',
+ id: 'lHkta9',
+ })}
+ value={intl.formatMessage(
+ {
+ defaultMessage:
+ '{postsCount, plural, =0 {No articles} one {# article} other {# articles}}',
+ description: 'ThematicPage: posts count meta',
+ id: 'iv3Ex1',
+ },
+ { postsCount: articles.length }
+ )}
+ />
+ ) : null}
+ </MetaList>
+ }
widgets={
thematics
? [
diff --git a/src/pages/thematique/[slug].tsx b/src/pages/thematique/[slug].tsx
index ea8c6b0..9220ccd 100644
--- a/src/pages/thematique/[slug].tsx
+++ b/src/pages/thematique/[slug].tsx
@@ -9,10 +9,11 @@ import {
getLayout,
Heading,
LinksWidget,
- type MetaItemData,
PageLayout,
PostsList,
Time,
+ MetaList,
+ MetaItem,
} from '../../components';
import {
getAllThematicsSlugs,
@@ -53,51 +54,6 @@ const ThematicPage: NextPageWithLayout<ThematicPageProps> = ({
url: `${ROUTES.THEMATICS.INDEX}/${slug}`,
});
- const headerMeta: (MetaItemData | undefined)[] = [
- {
- id: 'publication-date',
- label: intl.formatMessage({
- defaultMessage: 'Published on:',
- description: 'ThematicPage: publication date label',
- id: 'UTGhUU',
- }),
- value: <Time date={dates.publication} />,
- },
- dates.update
- ? {
- id: 'update-date',
- label: intl.formatMessage({
- defaultMessage: 'Updated on:',
- description: 'ThematicPage: update date label',
- id: '24FIsG',
- }),
- value: <Time date={dates.update} />,
- }
- : undefined,
- articles
- ? {
- id: 'total',
- label: intl.formatMessage({
- defaultMessage: 'Total:',
- description: 'ThematicPage: total label',
- id: 'lHkta9',
- }),
- value: intl.formatMessage(
- {
- defaultMessage:
- '{postsCount, plural, =0 {No articles} one {# article} other {# articles}}',
- description: 'ThematicPage: posts count meta',
- id: 'iv3Ex1',
- },
- { postsCount: articles.length }
- ),
- }
- : undefined,
- ];
- const filteredMeta = headerMeta.filter(
- (item): item is MetaItemData => !!item
- );
-
const { asPath } = useRouter();
const webpageSchema = getWebPageSchema({
description: seo.description,
@@ -154,7 +110,49 @@ const ThematicPage: NextPageWithLayout<ThematicPageProps> = ({
breadcrumbSchema={breadcrumbSchema}
title={title}
intro={intro}
- headerMeta={filteredMeta}
+ headerMeta={
+ <MetaList>
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Published on:',
+ description: 'Page: publication date label',
+ id: '4QbTDq',
+ })}
+ value={<Time date={dates.publication} />}
+ />
+ {dates.update ? (
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Updated on:',
+ description: 'Page: update date label',
+ id: 'Ez8Qim',
+ })}
+ value={<Time date={dates.update} />}
+ />
+ ) : null}
+ {articles ? (
+ <MetaItem
+ isInline
+ label={intl.formatMessage({
+ defaultMessage: 'Total:',
+ description: 'ThematicPage: total label',
+ id: 'lHkta9',
+ })}
+ value={intl.formatMessage(
+ {
+ defaultMessage:
+ '{postsCount, plural, =0 {No articles} one {# article} other {# articles}}',
+ description: 'ThematicPage: posts count meta',
+ id: 'iv3Ex1',
+ },
+ { postsCount: articles.length }
+ )}
+ />
+ ) : null}
+ </MetaList>
+ }
widgets={
topics
? [