diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-09-29 21:29:45 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-11 18:14:41 +0100 |
| commit | 4f768afe543bbf9e1857c41d03804f8e37ab3512 (patch) | |
| tree | d751219a147688b5665c51db3c8dbdca1f1345ee /src/components/organisms/widgets | |
| parent | 9128c224c65f8f2a172b22a443ccb4573c7acd90 (diff) | |
refactor(components): rewrite List component
* change `items` prop to children
* replace `kind` prop with `isHierarchical`, `isOrdered` & `isInline` props
* add `hideMarker` prop
* add `spacing` prop to control item spacing
* move lists styles to Sass placeholders to avoid repeats because of
headless WordPress
Diffstat (limited to 'src/components/organisms/widgets')
8 files changed, 67 insertions, 81 deletions
diff --git a/src/components/organisms/widgets/links-list-widget.module.scss b/src/components/organisms/widgets/links-list-widget.module.scss index 26f1549..4efc2d4 100644 --- a/src/components/organisms/widgets/links-list-widget.module.scss +++ b/src/components/organisms/widgets/links-list-widget.module.scss @@ -4,6 +4,8 @@ .widget { .list { .list { + padding: 0; + > *:first-child { border-top: fun.convert-px(1) solid var(--color-primary); } @@ -35,8 +37,6 @@ } &--ordered { - @extend %reset-ordered-list; - counter-reset: link; .list__link { @@ -50,10 +50,6 @@ } } - &--unordered { - @extend %reset-list; - } - &__item { &:not(:last-child) { border-bottom: fun.convert-px(1) solid var(--color-primary); diff --git a/src/components/organisms/widgets/links-list-widget.stories.tsx b/src/components/organisms/widgets/links-list-widget.stories.tsx index 3f62502..2180de4 100644 --- a/src/components/organisms/widgets/links-list-widget.stories.tsx +++ b/src/components/organisms/widgets/links-list-widget.stories.tsx @@ -1,4 +1,4 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; import { LinksListWidget } from './links-list-widget'; /** @@ -8,7 +8,7 @@ export default { title: 'Organisms/Widgets/LinksList', component: LinksListWidget, args: { - kind: 'unordered', + isOrdered: false, }, argTypes: { className: { @@ -32,21 +32,6 @@ export default { value: {}, }, }, - kind: { - control: { - type: 'select', - }, - description: 'The list kind: either ordered or unordered.', - options: ['ordered', 'unordered'], - table: { - category: 'Options', - defaultValue: { summary: 'unordered' }, - }, - type: { - name: 'string', - required: false, - }, - }, level: { control: { type: 'number', @@ -105,7 +90,6 @@ const items = [ export const Unordered = Template.bind({}); Unordered.args = { items, - kind: 'unordered', level: 2, title: 'A list of links', }; @@ -115,8 +99,8 @@ Unordered.args = { */ export const Ordered = Template.bind({}); Ordered.args = { + isOrdered: true, items, - kind: 'ordered', level: 2, title: 'A list of links', }; diff --git a/src/components/organisms/widgets/links-list-widget.test.tsx b/src/components/organisms/widgets/links-list-widget.test.tsx index 2d36eb5..6323e19 100644 --- a/src/components/organisms/widgets/links-list-widget.test.tsx +++ b/src/components/organisms/widgets/links-list-widget.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 { LinksListWidget } from './links-list-widget'; const title = 'Voluptatem minus autem'; @@ -14,20 +14,19 @@ describe('LinksListWidget', () => { it('renders a widget title', () => { render(<LinksListWidget items={items} title={title} level={2} />); expect( - screen.getByRole('heading', { level: 2, name: new RegExp(title, 'i') }) + rtlScreen.getByRole('heading', { level: 2, name: new RegExp(title, 'i') }) ).toBeInTheDocument(); }); it('renders the correct number of items', () => { render(<LinksListWidget items={items} title={title} level={2} />); - expect(screen.getAllByRole('listitem')).toHaveLength(items.length); + expect(rtlScreen.getAllByRole('listitem')).toHaveLength(items.length); }); it('renders some links', () => { render(<LinksListWidget items={items} title={title} level={2} />); - expect(screen.getByRole('link', { name: items[0].name })).toHaveAttribute( - 'href', - items[0].url - ); + expect( + rtlScreen.getByRole('link', { name: items[0].name }) + ).toHaveAttribute('href', items[0].url); }); }); diff --git a/src/components/organisms/widgets/links-list-widget.tsx b/src/components/organisms/widgets/links-list-widget.tsx index df8430d..8f71efd 100644 --- a/src/components/organisms/widgets/links-list-widget.tsx +++ b/src/components/organisms/widgets/links-list-widget.tsx @@ -1,6 +1,6 @@ -import { FC } from 'react'; +import type { FC } from 'react'; import { slugify } from '../../../utils/helpers'; -import { Link, List, type ListItem, type ListProps } from '../../atoms'; +import { Link, List, ListItem } from '../../atoms'; import { Widget, type WidgetProps } from '../../molecules'; import styles from './links-list-widget.module.scss'; @@ -19,13 +19,19 @@ export type LinksListItems = { url: string; }; -export type LinksListWidgetProps = Pick<WidgetProps, 'level' | 'title'> & - Pick<ListProps, 'className' | 'kind'> & { - /** - * An array of name/url couple. - */ - items: LinksListItems[]; - }; +export type LinksListWidgetProps = Pick<WidgetProps, 'level' | 'title'> & { + className?: string; + /** + * Should the links be ordered? + * + * @default false + */ + isOrdered?: boolean; + /** + * An array of name/url couple. + */ + items: LinksListItems[]; +}; /** * LinksListWidget component @@ -34,11 +40,11 @@ export type LinksListWidgetProps = Pick<WidgetProps, 'level' | 'title'> & */ export const LinksListWidget: FC<LinksListWidgetProps> = ({ className = '', + isOrdered = false, items, - kind = 'unordered', ...props }) => { - const listKindClass = `list--${kind}`; + const listKindClass = `list--${isOrdered ? 'ordered' : 'unordered'}`; /** * Format the widget data to be used as List items. @@ -46,19 +52,23 @@ export const LinksListWidget: FC<LinksListWidgetProps> = ({ * @param {LinksListItems[]} data - The widget data. * @returns {ListItem[]} The list items data. */ - const getListItems = (data: LinksListItems[]): ListItem[] => { - return data.map((item) => { - return { - id: slugify(item.name), - child: item.child && getListItems(item.child), - value: ( - <Link href={item.url} className={styles.list__link}> - {item.name} - </Link> - ), - }; - }); - }; + const getListItems = (data: LinksListItems[]) => + data.map((item) => ( + <ListItem className={styles.list__item} key={slugify(item.name)}> + <Link className={styles.list__link} href={item.url}> + {item.name} + </Link> + {item.child?.length ? ( + <List + className={`${styles.list} ${styles[listKindClass]} ${className}`} + hideMarker + isOrdered={isOrdered} + > + {getListItems(item.child)} + </List> + ) : null} + </ListItem> + )); return ( <Widget @@ -70,10 +80,11 @@ export const LinksListWidget: FC<LinksListWidgetProps> = ({ > <List className={`${styles.list} ${styles[listKindClass]} ${className}`} - items={getListItems(items)} - itemsClassName={styles.list__item} - kind={kind} - /> + hideMarker + isOrdered={isOrdered} + > + {getListItems(items)} + </List> </Widget> ); }; diff --git a/src/components/organisms/widgets/social-media.module.scss b/src/components/organisms/widgets/social-media.module.scss index b7191be..1cd3f57 100644 --- a/src/components/organisms/widgets/social-media.module.scss +++ b/src/components/organisms/widgets/social-media.module.scss @@ -1,10 +1,5 @@ @use "../../../styles/abstracts/placeholders"; .list { - @extend %reset-list; - - display: flex; - flex-flow: row wrap; - gap: var(--spacing-xs); padding: 0 var(--spacing-2xs); } diff --git a/src/components/organisms/widgets/social-media.tsx b/src/components/organisms/widgets/social-media.tsx index 40513f8..f9dea58 100644 --- a/src/components/organisms/widgets/social-media.tsx +++ b/src/components/organisms/widgets/social-media.tsx @@ -1,5 +1,5 @@ -import { FC } from 'react'; -import { SocialLink, type SocialLinkProps } from '../../atoms'; +import type { FC } from 'react'; +import { List, ListItem, SocialLink, type SocialLinkProps } from '../../atoms'; import { Widget, type WidgetProps } from '../../molecules'; import styles from './social-media.module.scss'; @@ -21,17 +21,18 @@ export const SocialMedia: FC<SocialMediaProps> = ({ media, ...props }) => { * @param {SocialMedia[]} links - An array of social media name and url. * @returns {JSX.Element[]} The social links. */ - const getItems = (links: Media[]): JSX.Element[] => { - return links.map((link, index) => ( - <li key={`media-${index}`}> + const getItems = (links: Media[]): JSX.Element[] => + links.map((link, index) => ( + <ListItem key={`media-${index}`}> <SocialLink name={link.name} url={link.url} /> - </li> + </ListItem> )); - }; return ( <Widget expanded={true} {...props}> - <ul className={styles.list}>{getItems(media)}</ul> + <List className={styles.list} hideMarker isInline spacing="xs"> + {getItems(media)} + </List> </Widget> ); }; diff --git a/src/components/organisms/widgets/table-of-contents.stories.tsx b/src/components/organisms/widgets/table-of-contents.stories.tsx index 3078e35..d464715 100644 --- a/src/components/organisms/widgets/table-of-contents.stories.tsx +++ b/src/components/organisms/widgets/table-of-contents.stories.tsx @@ -1,4 +1,4 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; import { TableOfContents as ToCWidget } from './table-of-contents'; /** @@ -26,7 +26,8 @@ const Template: ComponentStory<typeof ToCWidget> = (args) => ( <ToCWidget {...args} /> ); -const GetWrapper = () => { +/* eslint-disable max-statements */ +const getWrapper = () => { const wrapper = document.createElement('div'); const firstTitle = document.createElement('h2'); const firstParagraph = document.createElement('p'); @@ -50,5 +51,5 @@ const GetWrapper = () => { */ export const TableOfContents = Template.bind({}); TableOfContents.args = { - wrapper: GetWrapper(), + wrapper: getWrapper(), }; diff --git a/src/components/organisms/widgets/table-of-contents.tsx b/src/components/organisms/widgets/table-of-contents.tsx index 0e8789a..e67b495 100644 --- a/src/components/organisms/widgets/table-of-contents.tsx +++ b/src/components/organisms/widgets/table-of-contents.tsx @@ -1,4 +1,4 @@ -import { FC } from 'react'; +import type { FC } from 'react'; import { useIntl } from 'react-intl'; import { useHeadingsTree, type Heading } from '../../../utils/hooks'; import { type LinksListItems, LinksListWidget } from './links-list-widget'; @@ -31,21 +31,20 @@ export const TableOfContents: FC<TableOfContentsProps> = ({ wrapper }) => { * @param {Heading[]} tree - The headings tree. * @returns {LinksListItems[]} The list items. */ - const getItems = (tree: Heading[]): LinksListItems[] => { - return tree.map((heading) => { + const getItems = (tree: Heading[]): LinksListItems[] => + tree.map((heading) => { return { name: heading.title, url: `#${heading.id}`, child: getItems(heading.children), }; }); - }; return ( <LinksListWidget className={styles.list} + isOrdered items={getItems(headingsTree)} - kind="ordered" level={2} title={title} /> |
