From d5ade2359539648845a5854ed353b29367961d74 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Mon, 20 Nov 2023 11:02:20 +0100 Subject: refactor(components): extract MetaItem from MetaList * replace `items` prop on MetaList with `children` prop: it was too restrictive and the global options was not really useful. It is better too give control to the consumers. --- src/components/molecules/card/card.stories.tsx | 261 +++++++++------------ src/components/molecules/card/card.test.tsx | 13 +- .../molecules/layout/page-footer.stories.tsx | 23 +- .../molecules/layout/page-footer.test.tsx | 4 +- src/components/molecules/layout/page-footer.tsx | 13 +- .../molecules/layout/page-header.stories.tsx | 83 ++++--- .../molecules/layout/page-header.test.tsx | 8 +- src/components/molecules/layout/page-header.tsx | 7 +- .../molecules/meta-list/meta-list.stories.tsx | 9 +- .../molecules/meta-list/meta-list.test.tsx | 63 ++--- src/components/molecules/meta-list/meta-list.tsx | 72 ++---- .../comment/approved-comment/approved-comment.tsx | 26 +- .../post-preview-meta/post-preview-meta.tsx | 220 +++++++---------- .../project-overview/project-overview.tsx | 40 ++-- .../templates/page/page-layout.stories.tsx | 74 +++--- src/components/templates/page/page-layout.tsx | 15 +- 16 files changed, 423 insertions(+), 508 deletions(-) (limited to 'src/components') 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: ( - , - }, - ]} - /> + + + } + /> + ), }; @@ -107,27 +104,23 @@ export const FooterMeta = Template.bind({}); FooterMeta.args = { children: , meta: ( - Category 1 }, - { id: 'cat-2', value: Category 2 }, - ], - }, - { - id: 'tags', - label: 'Tags:', - value: [ - { id: 'tag-1', value: 'Tag 1' }, - { id: 'tag-2', value: 'Tag 2' }, - { id: 'tag-3', value: 'Tag 3' }, - ], - }, - ]} - /> + + Category 1 }, + { id: 'cat-2', value: Category 2 }, + ]} + /> + + ), }; @@ -155,17 +148,13 @@ CompositionTitleMeta.args = { children: ( The card title - , - }, - ]} - /> + + + } + /> + ), }; @@ -175,17 +164,13 @@ CompositionCoverTitleMeta.args = { children: ( The card title - , - }, - ]} - /> + + + } + /> + ), cover: ( @@ -250,17 +235,13 @@ CompositionTitleMetaBody.args = { <> The card title - , - }, - ]} - /> + + + } + /> + Nihil magnam tempora voluptatem. Reiciendis ut cum vel. Odit et @@ -278,17 +259,13 @@ CompositionCoverTitleMetaBody.args = { <> The card title - , - }, - ]} - /> + + + } + /> + Nihil magnam tempora voluptatem. Reiciendis ut cum vel. Odit et @@ -399,27 +376,23 @@ CompositionTitleBodyActionsMeta.args = { ), meta: ( - Category 1 }, - { id: 'cat-2', value: Category 2 }, - ], - }, - { - id: 'tags', - label: 'Tags:', - value: [ - { id: 'tag-1', value: 'Tag 1' }, - { id: 'tag-2', value: 'Tag 2' }, - { id: 'tag-3', value: 'Tag 3' }, - ], - }, - ]} - /> + + Category 1 }, + { id: 'cat-2', value: Category 2 }, + ]} + /> + + ), }; @@ -455,27 +428,23 @@ CompositionCoverTitleBodyActionsMeta.args = { ), meta: ( - Category 1 }, - { id: 'cat-2', value: Category 2 }, - ], - }, - { - id: 'tags', - label: 'Tags:', - value: [ - { id: 'tag-1', value: 'Tag 1' }, - { id: 'tag-2', value: 'Tag 2' }, - { id: 'tag-3', value: 'Tag 3' }, - ], - }, - ]} - /> + + Category 1 }, + { id: 'cat-2', value: Category 2 }, + ]} + /> + + ), }; @@ -485,17 +454,13 @@ CompositionAllContents.args = { <> The card title - , - }, - ]} - /> + + + } + /> + Nihil magnam tempora voluptatem. Reiciendis ut cum vel. Odit et @@ -522,26 +487,22 @@ CompositionAllContents.args = { ), meta: ( - Category 1 }, - { id: 'cat-2', value: Category 2 }, - ], - }, - { - id: 'tags', - label: 'Tags:', - value: [ - { id: 'tag-1', value: 'Tag 1' }, - { id: 'tag-2', value: 'Tag 2' }, - { id: 'tag-3', value: 'Tag 3' }, - ], - }, - ]} - /> + + Category 1 }, + { id: 'cat-2', value: Category 2 }, + ]} + /> + + ), }; 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( } + meta={ + + + + } > @@ -83,7 +88,11 @@ describe('Card', () => { render( } + meta={ + + + + } > {body} 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 = (args) => ( ); -const meta = [ - { - id: 'more-about', - label: 'More posts about:', - value: ( - - Topic name - - ), - }, -]; - /** * Page Footer Stories - With meta */ export const PageFooter = Template.bind({}); PageFooter.args = { - meta, + children: ( + + Topic name} + /> + + ), }; 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(); - 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 & { /** - * The footer metadata. + * The footer contents. */ - meta?: MetaItemData[]; + children?: ReactNode; }; /** @@ -14,8 +13,6 @@ export type PageFooterProps = Omit & { * * Render a footer to display page meta. */ -export const PageFooter: FC = ({ meta, ...props }) => ( -
- {meta ? : null} -
+export const PageFooter: FC = ({ children, ...props }) => ( +
{children}
); 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 = (args) => ( ); -const meta = [ - { id: 'publication-date', label: 'Published on:', value: '2022-04-09' }, - { - id: 'thematics', - label: 'Thematics:', - value: [ - { - id: 'cat-1', - value: ( - - Category 1 - - ), - }, - { - id: 'cat-2', - value: ( - - Category 2 - - ), - }, - ], - }, -]; - /** * Page Header Stories - Default */ @@ -111,7 +86,33 @@ WithIntro.args = { */ export const WithMeta = Template.bind({}); WithMeta.args = { - meta, + meta: ( + + + + Category 1 + + ), + }, + { + id: 'cat-2', + value: ( + + Category 2 + + ), + }, + ]} + /> + + ), 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: ( + + + + Category 1 + + ), + }, + { + id: 'cat-2', + value: ( + + Category 2 + + ), + }, + ]} + /> + + ), 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(); - expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent(title); + expect(rtlScreen.getByRole('heading', { level: 1 })).toHaveTextContent( + title + ); }); it('renders an introduction', () => { render(); - 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 = ({ {title} - {meta ? ( - - ) : null} + {meta} {intro ? getIntro() : null} 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 = (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 }) => ), }; /** @@ -65,6 +66,6 @@ Default.args = { */ export const Inlined = Template.bind({}); Inlined.args = { + children: items.map(({ 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(); + render( + + {items.map(({ id, ...item }) => ( + + ))} + + ); 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(); + render( + + {items.map(({ id, ...item }) => ( + + ))} + + ); 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(); + render( + + {items.map(({ id, ...item }) => ( + + ))} + + ); 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(); - - 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(); - - 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 & - Pick & { - /** - * 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 ( - {items.map(({ id, ...item }) => ( - - ))} + {children} ); }; 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 )} - -