diff options
Diffstat (limited to 'src/components/molecules/layout')
| -rw-r--r-- | src/components/molecules/layout/card.tsx | 10 | ||||
| -rw-r--r-- | src/components/molecules/layout/meta.module.scss | 17 | ||||
| -rw-r--r-- | src/components/molecules/layout/meta.stories.tsx | 34 | ||||
| -rw-r--r-- | src/components/molecules/layout/meta.test.tsx | 8 | ||||
| -rw-r--r-- | src/components/molecules/layout/meta.tsx | 103 | ||||
| -rw-r--r-- | src/components/molecules/layout/page-footer.tsx | 4 | ||||
| -rw-r--r-- | src/components/molecules/layout/page-header.tsx | 9 |
7 files changed, 81 insertions, 104 deletions
diff --git a/src/components/molecules/layout/card.tsx b/src/components/molecules/layout/card.tsx index 722e5a5..c9e7a90 100644 --- a/src/components/molecules/layout/card.tsx +++ b/src/components/molecules/layout/card.tsx @@ -72,15 +72,7 @@ export const Card: FC<CardProps> = ({ {tagline ? <div className={styles.tagline}>{tagline}</div> : null} {meta ? ( <footer className={styles.footer}> - <Meta - data={meta} - // eslint-disable-next-line react/jsx-no-literals -- Hardcoded config - layout="inline" - className={styles.list} - groupClassName={styles.meta__item} - labelClassName={styles.meta__label} - valueClassName={styles.meta__value} - /> + <Meta className={styles.list} data={meta} spacing="sm" /> </footer> ) : null} </article> diff --git a/src/components/molecules/layout/meta.module.scss b/src/components/molecules/layout/meta.module.scss index f572b65..26faac3 100644 --- a/src/components/molecules/layout/meta.module.scss +++ b/src/components/molecules/layout/meta.module.scss @@ -1,3 +1,16 @@ -.value { - word-break: break-all; +.list { + .description:not(:first-of-type) { + &::before { + display: inline; + float: left; + content: "/"; + margin-right: var(--itemSpacing); + } + } + + &--stack { + .term { + flex: 0 0 100%; + } + } } diff --git a/src/components/molecules/layout/meta.stories.tsx b/src/components/molecules/layout/meta.stories.tsx index 50ed252..6faa265 100644 --- a/src/components/molecules/layout/meta.stories.tsx +++ b/src/components/molecules/layout/meta.stories.tsx @@ -1,7 +1,5 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import descriptionListItemStories from '../../atoms/lists/description-list-group.stories'; -import descriptionListStories from '../../atoms/lists/description-list.stories'; -import { Meta as MetaComponent, MetaData } from './meta'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; +import { Meta as MetaComponent, type MetaData } from './meta'; /** * Meta - Storybook Meta @@ -9,12 +7,8 @@ import { Meta as MetaComponent, MetaData } from './meta'; export default { title: 'Molecules/Layout', component: MetaComponent, - args: { - itemsLayout: 'inline-values', - withSeparator: false, - }, + args: {}, argTypes: { - className: descriptionListStories.argTypes?.className, data: { description: 'The page metadata.', type: { @@ -23,24 +17,6 @@ export default { value: {}, }, }, - groupClassName: descriptionListStories.argTypes?.groupClassName, - itemsLayout: { - ...descriptionListItemStories.argTypes?.layout, - table: { - ...descriptionListItemStories.argTypes?.layout?.table, - defaultValue: { summary: 'inline-values' }, - }, - }, - labelClassName: descriptionListStories.argTypes?.labelClassName, - layout: descriptionListStories.argTypes?.layout, - valueClassName: descriptionListStories.argTypes?.valueClassName, - withSeparator: { - ...descriptionListStories.argTypes?.withSeparator, - table: { - ...descriptionListStories.argTypes?.withSeparator?.table, - defaultValue: { summary: true }, - }, - }, }, } as ComponentMeta<typeof MetaComponent>; @@ -51,10 +27,10 @@ const Template: ComponentStory<typeof MetaComponent> = (args) => ( const data: MetaData = { publication: { date: '2022-04-09', time: '01:04:00' }, thematics: [ - <a key="category1" href="#"> + <a key="category1" href="#a"> Category 1 </a>, - <a key="category2" href="#"> + <a key="category2" href="#b"> Category 2 </a>, ], diff --git a/src/components/molecules/layout/meta.test.tsx b/src/components/molecules/layout/meta.test.tsx index f19c408..0635fc3 100644 --- a/src/components/molecules/layout/meta.test.tsx +++ b/src/components/molecules/layout/meta.test.tsx @@ -1,15 +1,15 @@ import { describe, expect, it } from '@jest/globals'; -import { render, screen } from '../../../../tests/utils'; +import { render, screen as rtlScreen } from '../../../../tests/utils'; import { getFormattedDate } from '../../../utils/helpers'; import { Meta } from './meta'; const data = { publication: { date: '2022-04-09' }, thematics: [ - <a key="category1" href="#"> + <a key="category1" href="#a"> Category 1 </a>, - <a key="category2" href="#"> + <a key="category2" href="#b"> Category 2 </a>, ], @@ -19,7 +19,7 @@ describe('Meta', () => { it('format a date string', () => { render(<Meta data={data} />); expect( - screen.getByText(getFormattedDate(data.publication.date)) + rtlScreen.getByText(getFormattedDate(data.publication.date)) ).toBeInTheDocument(); }); }); diff --git a/src/components/molecules/layout/meta.tsx b/src/components/molecules/layout/meta.tsx index 53128a7..094c420 100644 --- a/src/components/molecules/layout/meta.tsx +++ b/src/components/molecules/layout/meta.tsx @@ -1,16 +1,19 @@ -import { FC, ReactNode } from 'react'; +import type { FC, ReactNode } from 'react'; import { useIntl } from 'react-intl'; import { getFormattedDate, getFormattedTime } from '../../../utils/helpers'; import { DescriptionList, type DescriptionListProps, - type DescriptionListItem, Link, + Group, + Term, + Description, } from '../../atoms'; +import styles from './meta.module.scss'; export type CustomMeta = { label: string; - value: ReactNode | ReactNode[]; + value: ReactNode; }; export type MetaComments = { @@ -106,24 +109,16 @@ export type MetaData = { website?: string; }; -export type MetaKey = keyof MetaData; +const isCustomMeta = ( + key: keyof MetaData, + _value: unknown +): _value is MetaData['custom'] => key === 'custom'; -export type MetaProps = Omit< - DescriptionListProps, - 'items' | 'withSeparator' -> & { +export type MetaProps = Omit<DescriptionListProps, 'children'> & { /** * The meta data. */ data: MetaData; - /** - * The items layout. - */ - itemsLayout?: DescriptionListItem['layout']; - /** - * If true, use a slash to delimitate multiple values. Default: true. - */ - withSeparator?: DescriptionListProps['withSeparator']; }; /** @@ -132,11 +127,13 @@ export type MetaProps = Omit< * Renders the given metadata. */ export const Meta: FC<MetaProps> = ({ + className = '', data, - itemsLayout = 'inline-values', - withSeparator = true, + isInline = false, ...props }) => { + const layoutClass = styles[isInline ? 'list--inline' : 'list--stack']; + const listClass = `${styles.list} ${layoutClass} ${className}`; const intl = useIntl(); /** @@ -316,7 +313,7 @@ export const Meta: FC<MetaProps> = ({ * @param {ValueOf<MetaData>} value - The meta value. * @returns {string|ReactNode|ReactNode[]} - The formatted value. */ - const getValue = <T extends MetaKey>( + const getValue = <T extends keyof MetaData>( key: T, value: MetaData[T] ): string | ReactNode | ReactNode[] => { @@ -338,12 +335,11 @@ export const Meta: FC<MetaProps> = ({ { postsCount: value as number } ); case 'website': - const url = value as string; - return ( - <Link href={url} external={true}> - {url} + return typeof value === 'string' ? ( + <Link href={value} external={true}> + {value} </Link> - ); + ) : null; default: return value as string | ReactNode | ReactNode[]; } @@ -355,36 +351,45 @@ export const Meta: FC<MetaProps> = ({ * @param {MetaData} items - The meta. * @returns {DescriptionListItem[]} The formatted description list items. */ - const getItems = (items: MetaData): DescriptionListItem[] => { - const listItems: DescriptionListItem[] = Object.entries(items) - .map(([key, value]) => { - if (!key || !value) return; - - const metaKey = key as MetaKey; + const getItems = (items: MetaData) => { + const entries = Object.entries(items) as [ + keyof MetaData, + MetaData[keyof MetaData], + ][]; + const listItems = entries.map(([key, meta]) => { + if (!meta) return null; - return { - id: metaKey, - label: - metaKey === 'custom' - ? (value as CustomMeta).label - : getLabel(metaKey), - layout: itemsLayout, - value: - metaKey === 'custom' && (value as CustomMeta) - ? (value as CustomMeta).value - : getValue(metaKey, value), - } as DescriptionListItem; - }) - .filter((item): item is DescriptionListItem => !!item); + return ( + <Group isInline key={key} spacing="2xs"> + <Term className={styles.term}> + {isCustomMeta(key, meta) ? meta.label : getLabel(key)} + </Term> + {Array.isArray(meta) ? ( + meta.map((singleMeta, index) => ( + /* eslint-disable-next-line react/no-array-index-key -- Unsafe, + * but also temporary. This component should be removed or + * refactored. */ + <Description className={styles.description} key={index}> + {isCustomMeta(key, singleMeta) + ? singleMeta + : getValue(key, singleMeta)} + </Description> + )) + ) : ( + <Description className={styles.description}> + {isCustomMeta(key, meta) ? meta.value : getValue(key, meta)} + </Description> + )} + </Group> + ); + }); return listItems; }; return ( - <DescriptionList - {...props} - items={getItems(data)} - withSeparator={withSeparator} - /> + <DescriptionList {...props} className={listClass} isInline={isInline}> + {getItems(data)} + </DescriptionList> ); }; diff --git a/src/components/molecules/layout/page-footer.tsx b/src/components/molecules/layout/page-footer.tsx index 5f3b176..375cbc4 100644 --- a/src/components/molecules/layout/page-footer.tsx +++ b/src/components/molecules/layout/page-footer.tsx @@ -15,7 +15,5 @@ export type PageFooterProps = Omit<FooterProps, 'children'> & { * Render a footer to display page meta. */ export const PageFooter: FC<PageFooterProps> = ({ meta, ...props }) => ( - <Footer {...props}> - {meta ? <Meta data={meta} withSeparator={false} /> : null} - </Footer> + <Footer {...props}>{meta ? <Meta data={meta} /> : null}</Footer> ); diff --git a/src/components/molecules/layout/page-header.tsx b/src/components/molecules/layout/page-header.tsx index 92650c5..b727cc1 100644 --- a/src/components/molecules/layout/page-header.tsx +++ b/src/components/molecules/layout/page-header.tsx @@ -56,14 +56,7 @@ export const PageHeader: FC<PageHeaderProps> = ({ {title} </Heading> {meta ? ( - <Meta - className={styles.meta} - data={meta} - // eslint-disable-next-line react/jsx-no-literals -- Layout allowed - itemsLayout="inline" - // eslint-disable-next-line react/jsx-no-literals -- Layout allowed - layout="column" - /> + <Meta className={styles.meta} data={meta} isInline spacing="xs" /> ) : null} {intro ? getIntro() : null} </div> |
