From 36890cfafeba6e30782df1260d7f9e678c7da4bf Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Mon, 2 Oct 2023 17:01:57 +0200 Subject: refactor(components): rewrite DescriptionList component * add a `spacing` prop * replace `layout` prop with `isInline` prop * remove `items` prop (and classNames props) in favor of new components: Description, Group, Term * remove `withSeparator` prop (CSS content is announced by screen readers and Firefox/Safari have no support for alternative text so the consumer should add itself an element with `aria-hidden` if it need a separator) Be aware, Meta component and its consumers can be visually broken, they should be refactored before using them in production. --- src/components/molecules/layout/meta.tsx | 103 ++++++++++++++++--------------- 1 file changed, 54 insertions(+), 49 deletions(-) (limited to 'src/components/molecules/layout/meta.tsx') 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 & { /** * 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 = ({ + 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 = ({ * @param {ValueOf} value - The meta value. * @returns {string|ReactNode|ReactNode[]} - The formatted value. */ - const getValue = ( + const getValue = ( key: T, value: MetaData[T] ): string | ReactNode | ReactNode[] => { @@ -338,12 +335,11 @@ export const Meta: FC = ({ { postsCount: value as number } ); case 'website': - const url = value as string; - return ( - - {url} + return typeof value === 'string' ? ( + + {value} - ); + ) : null; default: return value as string | ReactNode | ReactNode[]; } @@ -355,36 +351,45 @@ export const Meta: FC = ({ * @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 ( + + + {isCustomMeta(key, meta) ? meta.label : getLabel(key)} + + {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. */ + + {isCustomMeta(key, singleMeta) + ? singleMeta + : getValue(key, singleMeta)} + + )) + ) : ( + + {isCustomMeta(key, meta) ? meta.value : getValue(key, meta)} + + )} + + ); + }); return listItems; }; return ( - + + {getItems(data)} + ); }; -- cgit v1.2.3