From 4f768afe543bbf9e1857c41d03804f8e37ab3512 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Fri, 29 Sep 2023 21:29:45 +0200 Subject: 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 --- .../organisms/forms/ackee-toggle/ackee-toggle.tsx | 57 ++++++----- .../organisms/images/gallery.module.scss | 2 - .../organisms/images/gallery.stories.tsx | 4 +- src/components/organisms/images/gallery.tsx | 16 ++-- .../organisms/layout/cards-list.module.scss | 8 -- .../organisms/layout/cards-list.stories.tsx | 8 +- src/components/organisms/layout/cards-list.tsx | 71 +++++++------- .../organisms/layout/comments-list.fixture.ts | 106 +++++++++++++++++++++ .../organisms/layout/comments-list.fixture.tsx | 106 --------------------- .../organisms/layout/comments-list.module.scss | 16 ---- src/components/organisms/layout/comments-list.tsx | 31 ++++-- .../organisms/layout/posts-list.fixture.ts | 63 ++++++++++++ .../organisms/layout/posts-list.fixture.tsx | 63 ------------ .../organisms/layout/posts-list.module.scss | 6 -- src/components/organisms/layout/posts-list.tsx | 17 ++-- .../widgets/links-list-widget.module.scss | 8 +- .../widgets/links-list-widget.stories.tsx | 22 +---- .../organisms/widgets/links-list-widget.test.tsx | 13 ++- .../organisms/widgets/links-list-widget.tsx | 67 +++++++------ .../organisms/widgets/social-media.module.scss | 5 - src/components/organisms/widgets/social-media.tsx | 17 ++-- .../widgets/table-of-contents.stories.tsx | 7 +- .../organisms/widgets/table-of-contents.tsx | 9 +- 23 files changed, 343 insertions(+), 379 deletions(-) create mode 100644 src/components/organisms/layout/comments-list.fixture.ts delete mode 100644 src/components/organisms/layout/comments-list.fixture.tsx delete mode 100644 src/components/organisms/layout/comments-list.module.scss create mode 100644 src/components/organisms/layout/posts-list.fixture.ts delete mode 100644 src/components/organisms/layout/posts-list.fixture.tsx (limited to 'src/components/organisms') diff --git a/src/components/organisms/forms/ackee-toggle/ackee-toggle.tsx b/src/components/organisms/forms/ackee-toggle/ackee-toggle.tsx index 681d384..8ada948 100644 --- a/src/components/organisms/forms/ackee-toggle/ackee-toggle.tsx +++ b/src/components/organisms/forms/ackee-toggle/ackee-toggle.tsx @@ -1,17 +1,18 @@ -import { ChangeEvent, FC, useState } from 'react'; +/* eslint-disable max-statements */ +import { type ChangeEvent, type FC, useState, useCallback } from 'react'; import { useIntl } from 'react-intl'; import { type AckeeOptions, useLocalStorage, useUpdateAckeeOptions, } from '../../../../utils/hooks'; -import { Legend, List } from '../../../atoms'; +import { Legend, List, ListItem } from '../../../atoms'; import { Switch, - SwitchOption, - SwitchProps, + type SwitchOption, + type SwitchProps, Tooltip, - TooltipProps, + type TooltipProps, } from '../../../molecules'; export type AckeeToggleProps = Omit< @@ -85,29 +86,24 @@ export const AckeeToggle: FC = ({ id: '7zDlQo', }); - const options: [SwitchOption, SwitchOption] = [ - { - id: 'ackee-full', - label: fullLabel, - value: 'full', - }, - { - id: 'ackee-partial', - label: partialLabel, - value: 'partial', - }, - ]; + const options = [ + { id: 'ackee-full' as const, label: fullLabel, value: 'full' }, + { id: 'ackee-partial' as const, label: partialLabel, value: 'partial' }, + ] satisfies [SwitchOption, SwitchOption]; - const updateSetting = (e: ChangeEvent) => { - setValue(e.target.value === 'full' ? 'full' : 'partial'); - }; + const updateSetting = useCallback( + (e: ChangeEvent) => { + setValue(e.target.value === 'full' ? 'full' : 'partial'); + }, + [setValue] + ); - const closeTooltip = () => { + const closeTooltip = useCallback(() => { setIsTooltipOpened(false); - }; - const toggleTooltip = () => { + }, []); + const toggleTooltip = useCallback(() => { setIsTooltipOpened((prev) => !prev); - }; + }, []); return ( = ({ onClickOutside={closeTooltip} onToggle={toggleTooltip} > - + + {options.map((option) => ( + + {option.id === 'ackee-full' ? tooltipFull : tooltipPartial} + + ))} + } value={value} diff --git a/src/components/organisms/images/gallery.module.scss b/src/components/organisms/images/gallery.module.scss index f4faa63..31960a4 100644 --- a/src/components/organisms/images/gallery.module.scss +++ b/src/components/organisms/images/gallery.module.scss @@ -2,8 +2,6 @@ @use "../../../styles/abstracts/placeholders"; .wrapper { - @extend %reset-list; - display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--spacing-sm); diff --git a/src/components/organisms/images/gallery.stories.tsx b/src/components/organisms/images/gallery.stories.tsx index 8b68777..5005ed8 100644 --- a/src/components/organisms/images/gallery.stories.tsx +++ b/src/components/organisms/images/gallery.stories.tsx @@ -1,4 +1,4 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; import { ResponsiveImage } from '../../molecules'; import { Gallery } from './gallery'; @@ -37,7 +37,7 @@ export default { const image = { alt: 'Modi provident omnis', height: 480, - src: 'http://placeimg.com/640/480/fashion', + src: 'http://picsum.photos/640/480', width: 640, }; diff --git a/src/components/organisms/images/gallery.tsx b/src/components/organisms/images/gallery.tsx index ae773f6..b35acfe 100644 --- a/src/components/organisms/images/gallery.tsx +++ b/src/components/organisms/images/gallery.tsx @@ -1,7 +1,9 @@ -import { Children, FC, ReactElement } from 'react'; -import { type ResponsiveImageProps } from '../../molecules'; +import { Children, type FC, type ReactElement } from 'react'; +import { List, ListItem } from '../../atoms'; +import type { ResponsiveImageProps } from '../../molecules'; import styles from './gallery.module.scss'; +// eslint-disable-next-line @typescript-eslint/no-magic-numbers export type GalleryColumn = 2 | 3 | 4; export type GalleryProps = { @@ -24,10 +26,10 @@ export const Gallery: FC = ({ children, columns }) => { const columnsClass = `wrapper--${columns}-columns`; return ( -
    - {Children.map(children, (child) => { - return
  • {child}
  • ; - })} -
+ + {Children.map(children, (child) => ( + {child} + ))} + ); }; diff --git a/src/components/organisms/layout/cards-list.module.scss b/src/components/organisms/layout/cards-list.module.scss index ff79f33..8b18c08 100644 --- a/src/components/organisms/layout/cards-list.module.scss +++ b/src/components/organisms/layout/cards-list.module.scss @@ -17,14 +17,6 @@ gap: var(--spacing-lg); } } - - &--ordered { - @extend %reset-ordered-list; - } - - &--unordered { - @extend %reset-list; - } } .card { diff --git a/src/components/organisms/layout/cards-list.stories.tsx b/src/components/organisms/layout/cards-list.stories.tsx index b5f697a..1b5051f 100644 --- a/src/components/organisms/layout/cards-list.stories.tsx +++ b/src/components/organisms/layout/cards-list.stories.tsx @@ -1,4 +1,4 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; +import type { ComponentMeta, ComponentStory } from '@storybook/react'; import { CardsList as CardsListComponent, type CardsListItem, @@ -90,7 +90,7 @@ const items: CardsListItem[] = [ id: 'card-1', cover: { alt: 'card 1 picture', - src: 'http://placeimg.com/640/480', + src: 'http://picsum.photos/640/480', width: 640, height: 480, }, @@ -103,7 +103,7 @@ const items: CardsListItem[] = [ id: 'card-2', cover: { alt: 'card 2 picture', - src: 'http://placeimg.com/640/480', + src: 'http://picsum.photos/640/480', width: 640, height: 480, }, @@ -116,7 +116,7 @@ const items: CardsListItem[] = [ id: 'card-3', cover: { alt: 'card 3 picture', - src: 'http://placeimg.com/640/480', + src: 'http://picsum.photos/640/480', width: 640, height: 480, }, diff --git a/src/components/organisms/layout/cards-list.tsx b/src/components/organisms/layout/cards-list.tsx index e3d1156..29add3b 100644 --- a/src/components/organisms/layout/cards-list.tsx +++ b/src/components/organisms/layout/cards-list.tsx @@ -1,5 +1,5 @@ -import { FC } from 'react'; -import { List, type ListItem, type ListProps } from '../../atoms'; +import type { FC } from 'react'; +import { List, ListItem } from '../../atoms'; import { Card, type CardProps } from '../../molecules'; import styles from './cards-list.module.scss'; @@ -10,17 +10,22 @@ export type CardsListItem = Omit & { id: string; }; -export type CardsListProps = Pick & - Pick & { - /** - * Set additional classnames to the list wrapper. - */ - className?: string; - /** - * The cards data. - */ - items: CardsListItem[]; - }; +export type CardsListProps = Pick & { + /** + * Set additional classnames to the list wrapper. + */ + className?: string; + /** + * Should the cards list be ordered? + * + * @default false + */ + isOrdered?: boolean; + /** + * The cards data. + */ + items: CardsListItem[]; +}; /** * CardsList component @@ -29,40 +34,30 @@ export type CardsListProps = Pick & */ export const CardsList: FC = ({ className = '', + isOrdered = false, items, - kind = 'unordered', titleLevel, }) => { - const kindModifier = `wrapper--${kind}`; + const kindModifier = `wrapper--${isOrdered ? 'ordered' : 'unordered'}`; - /** - * Format the cards data to be used by the List component. - * - * @param {CardsListItem[]} cards - An array of card data. - * @returns {ListItem[]} The formatted cards data. - */ - const getCards = (cards: CardsListItem[]): ListItem[] => { - return cards.map(({ id, ...card }) => { - return { - id, - value: ( + return ( + + {items.map(({ id, ...item }) => ( + - ), - }; - }); - }; - - return ( - + + ))} + ); }; diff --git a/src/components/organisms/layout/comments-list.fixture.ts b/src/components/organisms/layout/comments-list.fixture.ts new file mode 100644 index 0000000..30a4f11 --- /dev/null +++ b/src/components/organisms/layout/comments-list.fixture.ts @@ -0,0 +1,106 @@ +import type { SingleComment } from '../../../types/app'; + +export const comments: SingleComment[] = [ + { + approved: true, + content: + 'Voluptas ducimus inventore. Libero ut et doloribus. Earum nostrum ab. Aliquam rem dolores omnis voluptate. Sunt aut ut et.', + id: 1, + meta: { + author: { + avatar: { + alt: 'Author 1 avatar', + height: 480, + src: 'http://picsum.photos/640/480', + width: 640, + }, + name: 'Author 1', + }, + date: '2021-04-03 18:04:11', + }, + parentId: 0, + replies: [], + }, + { + approved: true, + content: + 'Sit sed error quasi voluptatem velit voluptas aut. Aut debitis eveniet. Praesentium dolores quia voluptate vero quis dicta quasi vel. Aut voluptas accusantium ut aut quidem consectetur itaque laboriosam rerum.', + id: 2, + meta: { + author: { + avatar: { + alt: 'Author 2 avatar', + height: 480, + src: 'http://picsum.photos/640/480', + width: 640, + }, + name: 'Author 2', + website: '#', + }, + date: '2021-04-03 23:30:20', + }, + parentId: 0, + replies: [ + { + approved: true, + content: + 'Vel ullam in porro tempore. Maiores quos quia magnam beatae nemo libero velit numquam. Sapiente aliquid cumque. Velit neque in adipisci aut assumenda voluptates earum. Autem esse autem provident in tempore. Aut distinctio dolor qui repellat et et adipisci velit aspernatur.', + id: 4, + meta: { + author: { + avatar: { + alt: 'Author 4 avatar', + height: 480, + src: 'http://picsum.photos/640/480', + width: 640, + }, + name: 'Author 4', + }, + date: '2021-04-03 23:04:24', + }, + parentId: 2, + replies: [], + }, + { + approved: true, + content: + 'Sed non omnis. Quam porro est. Quae tempore quae. Exercitationem eos non velit voluptatem velit voluptas iusto. Sit debitis qui ipsam quo asperiores numquam veniam praesentium ut.', + id: 5, + meta: { + author: { + avatar: { + alt: 'Author 1 avatar', + height: 480, + src: 'http://picsum.photos/640/480', + width: 640, + }, + name: 'Author 1', + }, + date: '2021-04-04 08:05:14', + }, + parentId: 2, + replies: [], + }, + ], + }, + { + approved: false, + content: + 'Natus consequatur maiores aperiam dolore eius nesciunt ut qui et. Ab ea nobis est. Eaque dolor corrupti id aut. Impedit architecto autem qui neque rerum ab dicta dignissimos voluptates.', + id: 3, + meta: { + author: { + avatar: { + alt: 'Author 3', + height: 480, + src: 'http://picsum.photos/640/480', + width: 640, + }, + name: 'Author 3', + }, + date: '2021-09-13 13:24:54', + }, + parentId: 0, + replies: [], + }, +]; diff --git a/src/components/organisms/layout/comments-list.fixture.tsx b/src/components/organisms/layout/comments-list.fixture.tsx deleted file mode 100644 index 5842129..0000000 --- a/src/components/organisms/layout/comments-list.fixture.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import { SingleComment } from '../../../types/app'; - -export const comments: SingleComment[] = [ - { - approved: true, - content: - 'Voluptas ducimus inventore. Libero ut et doloribus. Earum nostrum ab. Aliquam rem dolores omnis voluptate. Sunt aut ut et.', - id: 1, - meta: { - author: { - avatar: { - alt: 'Author 1 avatar', - height: 480, - src: 'http://placeimg.com/640/480', - width: 640, - }, - name: 'Author 1', - }, - date: '2021-04-03 18:04:11', - }, - parentId: 0, - replies: [], - }, - { - approved: true, - content: - 'Sit sed error quasi voluptatem velit voluptas aut. Aut debitis eveniet. Praesentium dolores quia voluptate vero quis dicta quasi vel. Aut voluptas accusantium ut aut quidem consectetur itaque laboriosam occaecati.', - id: 2, - meta: { - author: { - avatar: { - alt: 'Author 2 avatar', - height: 480, - src: 'http://placeimg.com/640/480', - width: 640, - }, - name: 'Author 2', - website: '#', - }, - date: '2021-04-03 23:30:20', - }, - parentId: 0, - replies: [ - { - approved: true, - content: - 'Vel ullam in porro tempore. Maiores quos quia magnam beatae nemo libero velit numquam. Sapiente aliquid cumque. Velit neque in adipisci aut assumenda voluptates earum. Autem esse autem provident in tempore. Aut distinctio dolor qui repellat et et adipisci velit aspernatur.', - id: 4, - meta: { - author: { - avatar: { - alt: 'Author 4 avatar', - height: 480, - src: 'http://placeimg.com/640/480', - width: 640, - }, - name: 'Author 4', - }, - date: '2021-04-03 23:04:24', - }, - parentId: 2, - replies: [], - }, - { - approved: true, - content: - 'Sed non omnis. Quam porro est. Quae tempore quae. Exercitationem eos non velit voluptatem velit voluptas iusto. Sit debitis qui ipsam quo asperiores numquam veniam praesentium ut.', - id: 5, - meta: { - author: { - avatar: { - alt: 'Author 1 avatar', - height: 480, - src: 'http://placeimg.com/640/480', - width: 640, - }, - name: 'Author 1', - }, - date: '2021-04-04 08:05:14', - }, - parentId: 2, - replies: [], - }, - ], - }, - { - approved: false, - content: - 'Natus consequatur maiores aperiam dolore eius nesciunt ut qui et. Ab ea nobis est. Eaque dolor corrupti id aut. Impedit architecto autem qui neque rerum ab dicta dignissimos voluptates.', - id: 3, - meta: { - author: { - avatar: { - alt: 'Author 3', - height: 480, - src: 'http://placeimg.com/640/480', - width: 640, - }, - name: 'Author 3', - }, - date: '2021-09-13 13:24:54', - }, - parentId: 0, - replies: [], - }, -]; diff --git a/src/components/organisms/layout/comments-list.module.scss b/src/components/organisms/layout/comments-list.module.scss deleted file mode 100644 index f7a0cf0..0000000 --- a/src/components/organisms/layout/comments-list.module.scss +++ /dev/null @@ -1,16 +0,0 @@ -@use "../../../styles/abstracts/placeholders"; - -.list { - @extend %reset-ordered-list; - - & & { - margin: var(--spacing-sm) 0; - padding-left: var(--spacing-sm); - } -} - -.item { - &:not(:last-child) { - margin-bottom: var(--spacing-sm); - } -} diff --git a/src/components/organisms/layout/comments-list.tsx b/src/components/organisms/layout/comments-list.tsx index 1ce0cf5..103bfb4 100644 --- a/src/components/organisms/layout/comments-list.tsx +++ b/src/components/organisms/layout/comments-list.tsx @@ -1,7 +1,12 @@ -import { FC } from 'react'; -import { type SingleComment } from '../../../types'; +import type { FC } from 'react'; +import type { SingleComment } from '../../../types'; +import { List, ListItem } from '../../atoms'; + +// eslint-disable-next-line @typescript-eslint/no-shadow import { Comment, type CommentProps } from './comment'; -import styles from './comments-list.module.scss'; + +// eslint-disable-next-line @typescript-eslint/no-magic-numbers +export type CommentsListDepth = 0 | 1 | 2 | 3 | 4; export type CommentsListProps = Pick & { /** @@ -11,7 +16,7 @@ export type CommentsListProps = Pick & { /** * The maximum depth. Use `0` to not display nested comments. */ - depth: 0 | 1 | 2 | 3 | 4; + depth: CommentsListDepth; }; /** @@ -38,19 +43,25 @@ export const CommentsList: FC = ({ const isLastLevel = startLevel === depth; return commentsList.map(({ replies, ...comment }) => ( -
  • + - {replies && !isLastLevel && ( -
      {getItems(replies, startLevel + 1)}
    - )} -
  • + {replies.length && !isLastLevel ? ( + + {getItems(replies, startLevel + 1)} + + ) : null} + )); }; - return
      {getItems(comments, 0)}
    ; + return ( + + {getItems(comments, 0)} + + ); }; diff --git a/src/components/organisms/layout/posts-list.fixture.ts b/src/components/organisms/layout/posts-list.fixture.ts new file mode 100644 index 0000000..6109411 --- /dev/null +++ b/src/components/organisms/layout/posts-list.fixture.ts @@ -0,0 +1,63 @@ +import type { Post } from './posts-list'; + +export const introPost1 = + 'Esse et voluptas sapiente modi impedit unde et. Ducimus nulla ea impedit sit placeat nihil assumenda. Rem est fugiat amet quo hic. Corrupti fuga quod animi autem dolorem ullam corrupti vel aut.'; + +export const introPost2 = + 'Illum quae asperiores quod aut necessitatibus itaque excepturi voluptas. Incidunt exercitationem ullam saepe alias consequatur sed. Quam veniam quaerat voluptatum earum quia quisquam fugiat sed perspiciatis. Et velit saepe est recusandae facilis eos eum ipsum.'; + +export const introPost3 = + 'Sunt aperiam ut rem impedit dolor id sit. Reprehenderit ipsum iusto fugiat. Quaerat laboriosam magnam facilis. Totam sint aliquam voluptatem in quis laborum sunt eum. Enim aut debitis officiis porro iure quia nihil voluptas ipsum. Praesentium quis necessitatibus cumque quia qui velit quos dolorem.'; + +export const cover = { + alt: 'cover', + height: 480, + src: 'http://picsum.photos/640/480', + width: 640, +}; + +export const posts: Post[] = [ + { + intro: introPost1, + id: 'post-1', + meta: { + cover, + dates: { publication: '2022-02-26' }, + wordsCount: introPost1.split(' ').length, + thematics: [ + { id: 1, name: 'Cat 1', url: '#' }, + { id: 2, name: 'Cat 2', url: '#' }, + ], + commentsCount: 1, + }, + title: 'Ratione velit fuga', + url: '#', + }, + { + intro: introPost2, + id: 'post-2', + meta: { + dates: { publication: '2022-02-20' }, + wordsCount: introPost2.split(' ').length, + thematics: [{ id: 2, name: 'Cat 2', url: '#' }], + commentsCount: 0, + }, + title: 'Debitis laudantium laudantium', + url: '#', + }, + { + intro: introPost3, + id: 'post-3', + meta: { + cover, + dates: { publication: '2021-12-20' }, + wordsCount: introPost3.split(' ').length, + thematics: [{ id: 1, name: 'Cat 1', url: '#' }], + commentsCount: 3, + }, + title: 'Quaerat ut corporis', + url: '#', + }, +]; + +export const searchPage = '#'; diff --git a/src/components/organisms/layout/posts-list.fixture.tsx b/src/components/organisms/layout/posts-list.fixture.tsx deleted file mode 100644 index 97a746f..0000000 --- a/src/components/organisms/layout/posts-list.fixture.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { type Post } from './posts-list'; - -export const introPost1 = - 'Esse et voluptas sapiente modi impedit unde et. Ducimus nulla ea impedit sit placeat nihil assumenda. Rem est fugiat amet quo hic. Corrupti fuga quod animi autem dolorem ullam corrupti vel aut.'; - -export const introPost2 = - 'Illum quae asperiores quod aut necessitatibus itaque excepturi voluptas. Incidunt exercitationem ullam saepe alias consequatur sed. Quam veniam quaerat voluptatum earum quia quisquam fugiat sed perspiciatis. Et velit saepe est recusandae facilis eos eum ipsum.'; - -export const introPost3 = - 'Sunt aperiam ut rem impedit dolor id sit. Reprehenderit ipsum iusto fugiat. Quaerat laboriosam magnam facilis. Totam sint aliquam voluptatem in quis laborum sunt eum. Enim aut debitis officiis porro iure quia nihil voluptas ipsum. Praesentium quis necessitatibus cumque quia qui velit quos dolorem.'; - -export const cover = { - alt: 'cover', - height: 480, - src: 'http://placeimg.com/640/480', - width: 640, -}; - -export const posts: Post[] = [ - { - intro: introPost1, - id: 'post-1', - meta: { - cover, - dates: { publication: '2022-02-26' }, - wordsCount: introPost1.split(' ').length, - thematics: [ - { id: 1, name: 'Cat 1', url: '#' }, - { id: 2, name: 'Cat 2', url: '#' }, - ], - commentsCount: 1, - }, - title: 'Ratione velit fuga', - url: '#', - }, - { - intro: introPost2, - id: 'post-2', - meta: { - dates: { publication: '2022-02-20' }, - wordsCount: introPost2.split(' ').length, - thematics: [{ id: 2, name: 'Cat 2', url: '#' }], - commentsCount: 0, - }, - title: 'Debitis laudantium laudantium', - url: '#', - }, - { - intro: introPost3, - id: 'post-3', - meta: { - cover, - dates: { publication: '2021-12-20' }, - wordsCount: introPost3.split(' ').length, - thematics: [{ id: 1, name: 'Cat 1', url: '#' }], - commentsCount: 3, - }, - title: 'Quaerat ut corporis', - url: '#', - }, -]; - -export const searchPage = '#'; diff --git a/src/components/organisms/layout/posts-list.module.scss b/src/components/organisms/layout/posts-list.module.scss index 49993da..759902a 100644 --- a/src/components/organisms/layout/posts-list.module.scss +++ b/src/components/organisms/layout/posts-list.module.scss @@ -18,14 +18,8 @@ } .list { - @extend %reset-ordered-list; - .item { border-bottom: fun.convert-px(1) solid var(--color-border); - - &:not(:last-child) { - margin-bottom: var(--spacing-md); - } } } diff --git a/src/components/organisms/layout/posts-list.tsx b/src/components/organisms/layout/posts-list.tsx index 86c3d12..cde81e6 100644 --- a/src/components/organisms/layout/posts-list.tsx +++ b/src/components/organisms/layout/posts-list.tsx @@ -8,6 +8,8 @@ import { type HeadingLevel, ProgressBar, Spinner, + List, + ListItem, } from '../../atoms'; import { Pagination, type PaginationProps } from '../../molecules'; import { NoResults, type NoResultsProps } from './no-results'; @@ -115,25 +117,28 @@ export const PostsList: FC = ({ allPosts: Post[], headingLevel: HeadingLevel = 2 ): JSX.Element => ( -
      {allPosts.map(({ id, ...post }) => ( -
    1. + -
    2. + {id === lastPostId && ( -
    3. + -
    4. + )}
      ))} -
    +
    ); /** 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(); 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(); - expect(screen.getAllByRole('listitem')).toHaveLength(items.length); + expect(rtlScreen.getAllByRole('listitem')).toHaveLength(items.length); }); it('renders some links', () => { render(); - 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 & - Pick & { - /** - * An array of name/url couple. - */ - items: LinksListItems[]; - }; +export type LinksListWidgetProps = Pick & { + 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 & */ export const LinksListWidget: FC = ({ 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 = ({ * @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: ( - - {item.name} - - ), - }; - }); - }; + const getListItems = (data: LinksListItems[]) => + data.map((item) => ( + + + {item.name} + + {item.child?.length ? ( + + {getListItems(item.child)} + + ) : null} + + )); return ( = ({ > + hideMarker + isOrdered={isOrdered} + > + {getListItems(items)} + ); }; 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 = ({ 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) => ( -
  • + const getItems = (links: Media[]): JSX.Element[] => + links.map((link, index) => ( + -
  • + )); - }; return ( -
      {getItems(media)}
    + + {getItems(media)} +
    ); }; 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 = (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 = ({ 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 ( -- cgit v1.2.3