From c153f93dc8691a71dc76aad3dd618298da9d238a Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Tue, 17 Oct 2023 19:46:08 +0200 Subject: refactor(components): rewrite Card component * make the component more generic * merge `` and `` styles into card component to avoid repeating the same structure * remove most of the props to use composition However the CSS is a bit complex because of the two variants... Also, the component should be refactored when the CSS pseudo-class `:has` has enough support: the provider and the `cover` and `meta` props should be removed. --- .../organisms/layout/cards-list.module.scss | 2 +- .../organisms/layout/cards-list.stories.tsx | 145 ++++++-------------- .../organisms/layout/cards-list.test.tsx | 93 ++++++------- src/components/organisms/layout/cards-list.tsx | 25 ++-- .../organisms/layout/comment.module.scss | 150 +++++++-------------- src/components/organisms/layout/comment.tsx | 121 +++++++++-------- .../organisms/layout/summary.module.scss | 105 +-------------- src/components/organisms/layout/summary.tsx | 92 +++++++------ 8 files changed, 264 insertions(+), 469 deletions(-) (limited to 'src/components/organisms') diff --git a/src/components/organisms/layout/cards-list.module.scss b/src/components/organisms/layout/cards-list.module.scss index 8b18c08..1665829 100644 --- a/src/components/organisms/layout/cards-list.module.scss +++ b/src/components/organisms/layout/cards-list.module.scss @@ -19,6 +19,6 @@ } } -.card { +.item > * { height: 100%; } diff --git a/src/components/organisms/layout/cards-list.stories.tsx b/src/components/organisms/layout/cards-list.stories.tsx index 03feee7..3f8e72a 100644 --- a/src/components/organisms/layout/cards-list.stories.tsx +++ b/src/components/organisms/layout/cards-list.stories.tsx @@ -1,4 +1,5 @@ import type { ComponentMeta, ComponentStory } from '@storybook/react'; +import { Card, CardBody, CardHeader, CardTitle } from '../../molecules'; import { CardsList as CardsListComponent, type CardsListItem, @@ -10,39 +11,7 @@ import { export default { title: 'Organisms/Layout', component: CardsListComponent, - args: { - coverFit: 'cover', - kind: 'unordered', - }, argTypes: { - className: { - control: { - type: 'text', - }, - description: 'Set additional classnames to the list wrapper.', - table: { - category: 'Styles', - }, - type: { - name: 'string', - required: false, - }, - }, - coverFit: { - control: { - type: 'select', - }, - description: 'The cover fit.', - options: ['fill', 'contain', 'cover', 'none', 'scale-down'], - table: { - category: 'Options', - defaultValue: { summary: 'cover' }, - }, - type: { - name: 'string', - required: false, - }, - }, items: { description: 'The cards data.', type: { @@ -51,33 +20,20 @@ export default { value: {}, }, }, - kind: { + isOrdered: { control: { - type: 'select', + type: 'boolean', }, - description: 'The list kind.', - options: ['ordered', 'unordered'], + description: 'Should the list be ordered?', table: { category: 'Options', - defaultValue: { summary: 'unordered' }, + defaultValue: { summary: false }, }, type: { - name: 'string', + name: 'boolean', required: false, }, }, - titleLevel: { - control: { - type: 'number', - min: 1, - max: 6, - }, - description: 'The heading level for each card.', - type: { - name: 'number', - required: true, - }, - }, }, } as ComponentMeta; @@ -88,63 +44,49 @@ const Template: ComponentStory = (args) => ( const items: CardsListItem[] = [ { id: 'card-1', - cover: { - alt: 'card 1 picture', - src: 'https://picsum.photos/640/480', - width: 640, - height: 480, - }, - meta: [ - { - id: 'categories', - label: 'Categories', - value: [ - { id: 'velit', value: 'Velit' }, - { id: 'ex', value: 'Ex' }, - { id: 'alias', value: 'Alias' }, - ], - }, - ], - tagline: 'Molestias ut error', - title: 'Et alias omnis', - url: '#', + card: ( + + + Et alias omnis + + + Rerum voluptatem sint sint sit dignissimos. Labore totam possimus + tempore atque veniam. Doloremque tenetur quidem beatae veritatis quo. + Quaerat voluptatem deleniti voluptas quia. Qui voluptatem iure iste + expedita et sed beatae. + + + ), }, { id: 'card-2', - cover: { - alt: 'card 2 picture', - src: 'https://picsum.photos/640/480', - width: 640, - height: 480, - }, - meta: [{ id: 'categories', label: 'Categories', value: 'Voluptas' }], - tagline: 'Quod vel accusamus', - title: 'Laboriosam doloremque mollitia', - url: '#', + card: ( + + + Fugiat magnam nesciunt + + + Sit corporis animi ea. Earum asperiores error et. Aliquid quia et + consequatur. Magnam sit ut facere explicabo vel dolorem earum + assumenda. Aspernatur inventore quod libero est. + + + ), }, { id: 'card-3', - cover: { - alt: 'card 3 picture', - src: 'https://picsum.photos/640/480', - width: 640, - height: 480, - }, - meta: [ - { - id: 'categories', - label: 'Categories', - value: [ - { id: 'quisquam', value: 'Quisquam' }, - { id: 'quia', value: 'Quia' }, - { id: 'sapiente', value: 'Sapiente' }, - { id: 'perspiciatis', value: 'Perspiciatis' }, - ], - }, - ], - tagline: 'Quo error eum', - title: 'Magni rem nulla', - url: '#', + card: ( + + + Asperiores eum quas + + + Doloremque ut cupiditate distinctio aperiam. Neque tempora unde + perferendis asperiores. Doloremque velit vel quam. Temporibus itaque + non non exercitationem. + + + ), }, ]; @@ -154,5 +96,4 @@ const items: CardsListItem[] = [ export const CardsList = Template.bind({}); CardsList.args = { items, - titleLevel: 2, }; diff --git a/src/components/organisms/layout/cards-list.test.tsx b/src/components/organisms/layout/cards-list.test.tsx index c9d6ae7..b04e109 100644 --- a/src/components/organisms/layout/cards-list.test.tsx +++ b/src/components/organisms/layout/cards-list.test.tsx @@ -1,73 +1,60 @@ import { describe, expect, it } from '@jest/globals'; -import { render, screen as rtlScreen } from '../../../../tests/utils'; +import { render, screen as rtlScreen } from '@testing-library/react'; +import { Card, CardBody, CardHeader, CardTitle } from '../../molecules'; import { CardsList, type CardsListItem } from './cards-list'; const items: CardsListItem[] = [ { id: 'card-1', - cover: { - alt: 'card 1 picture', - src: 'https://picsum.photos/640/480', - width: 640, - height: 480, - }, - meta: [ - { - id: 'categories', - label: 'Categories', - value: [ - { id: 'velit', value: 'Velit' }, - { id: 'ex', value: 'Ex' }, - { id: 'alias', value: 'Alias' }, - ], - }, - ], - tagline: 'Molestias ut error', - title: 'Et alias omnis', - url: '#', + card: ( + + + Et alias omnis + + + Rerum voluptatem sint sint sit dignissimos. Labore totam possimus + tempore atque veniam. Doloremque tenetur quidem beatae veritatis quo. + Quaerat voluptatem deleniti voluptas quia. Qui voluptatem iure iste + expedita et sed beatae. + + + ), }, { id: 'card-2', - cover: { - alt: 'card 2 picture', - src: 'https://picsum.photos/640/480', - width: 640, - height: 480, - }, - meta: [{ id: 'categories', label: 'Categories', value: 'Voluptas' }], - tagline: 'Quod vel accusamus', - title: 'Laboriosam doloremque mollitia', - url: '#', + card: ( + + + Fugiat magnam nesciunt + + + Sit corporis animi ea. Earum asperiores error et. Aliquid quia et + consequatur. Magnam sit ut facere explicabo vel dolorem earum + assumenda. Aspernatur inventore quod libero est. + + + ), }, { id: 'card-3', - cover: { - alt: 'card 3 picture', - src: 'https://picsum.photos/640/480', - width: 640, - height: 480, - }, - meta: [ - { - id: 'categories', - label: 'Categories', - value: [ - { id: 'quisquam', value: 'Quisquam' }, - { id: 'quia', value: 'Quia' }, - { id: 'sapiente', value: 'Sapiente' }, - { id: 'perspiciatis', value: 'Perspiciatis' }, - ], - }, - ], - tagline: 'Quo error eum', - title: 'Magni rem nulla', - url: '#', + card: ( + + + Asperiores eum quas + + + Doloremque ut cupiditate distinctio aperiam. Neque tempora unde + perferendis asperiores. Doloremque velit vel quam. Temporibus itaque + non non exercitationem. + + + ), }, ]; describe('CardsList', () => { it('renders a list of cards', () => { - render(); + render(); expect(rtlScreen.getAllByRole('heading', { level: 2 })).toHaveLength( items.length ); diff --git a/src/components/organisms/layout/cards-list.tsx b/src/components/organisms/layout/cards-list.tsx index 29add3b..4f920e8 100644 --- a/src/components/organisms/layout/cards-list.tsx +++ b/src/components/organisms/layout/cards-list.tsx @@ -1,16 +1,20 @@ -import type { FC } from 'react'; +import type { FC, ReactElement } from 'react'; import { List, ListItem } from '../../atoms'; -import { Card, type CardProps } from '../../molecules'; +import type { CardProps } from '../../molecules'; import styles from './cards-list.module.scss'; -export type CardsListItem = Omit & { +export type CardsListItem = { + /** + * The card. + */ + card: ReactElement | CardProps>; /** * The card id. */ id: string; }; -export type CardsListProps = Pick & { +export type CardsListProps = { /** * Set additional classnames to the list wrapper. */ @@ -36,7 +40,6 @@ export const CardsList: FC = ({ className = '', isOrdered = false, items, - titleLevel, }) => { const kindModifier = `wrapper--${isOrdered ? 'ordered' : 'unordered'}`; @@ -47,15 +50,9 @@ export const CardsList: FC = ({ isInline isOrdered={isOrdered} > - {items.map(({ id, ...item }) => ( - - + {items.map(({ id, card }) => ( + + {card} ))} diff --git a/src/components/organisms/layout/comment.module.scss b/src/components/organisms/layout/comment.module.scss index bf8aada..f26b3fe 100644 --- a/src/components/organisms/layout/comment.module.scss +++ b/src/components/organisms/layout/comment.module.scss @@ -2,132 +2,72 @@ @use "../../../styles/abstracts/mixins" as mix; @use "../../../styles/abstracts/placeholders"; -.wrapper { - padding: var(--spacing-md); - background: var(--color-bg); - border: fun.convert-px(1) solid var(--color-border); - box-shadow: - fun.convert-px(3) fun.convert-px(3) 0 0 var(--color-shadow-light), - fun.convert-px(4) fun.convert-px(4) fun.convert-px(3) fun.convert-px(-2) - var(--color-shadow); - - &--comment { - @include mix.media("screen") { - @include mix.dimensions("sm") { - display: grid; - grid-template-columns: minmax(0, #{fun.convert-px(150)}) minmax(0, 1fr); - column-gap: var(--spacing-lg); - } - } - } - - &--form { - display: flex; - flex-flow: column wrap; - place-content: center; - margin-top: var(--spacing-sm); - } - - .header { - display: flex; - flex-flow: column wrap; - align-items: center; - row-gap: var(--spacing-sm); - - @include mix.media("screen") { - @include mix.dimensions("sm") { - grid-row: 1 / 4; - } - } - } - - .author { - color: var(--color-primary-darker); - font-weight: 600; - text-align: center; - } - - .avatar { - width: fun.convert-px(85); - height: fun.convert-px(85); - position: relative; +.avatar { + img { border-radius: fun.convert-px(3); box-shadow: 0 0 0 fun.convert-px(1) var(--color-shadow-light), fun.convert-px(2) fun.convert-px(2) 0 fun.convert-px(1) var(--color-shadow); - - img { - border-radius: fun.convert-px(3); - } } +} - .date { - margin: var(--spacing-sm) 0; - font-size: var(--font-size-sm); +.author { + color: var(--color-primary-darker); + font-family: var(--font-family-regular); + font-size: var(--font-size-md); + font-weight: 600; + text-align: center; + text-shadow: none; +} - &__item { - justify-content: center; - } +.body { + overflow-wrap: break-word; - @include mix.media("screen") { - @include mix.dimensions("sm") { - margin: 0 0 var(--spacing-sm); + :global { + a { + @extend %link; - &__item { - justify-content: left; - } + &[hreflang], + &.download, + &.external { + @extend %link-with-icon; } - } - } - - .body { - overflow-wrap: break-word; - - :global { - a { - @extend %link; - &[hreflang], - &.download, - &.external { - @extend %link-with-icon; - } - - &[hreflang] { - @extend %link-with-lang; - } + &[hreflang] { + @extend %link-with-lang; + } - &[hreflang]:not(.download, .external) { - --is-icon-hidden: ""; - } + &[hreflang]:not(.download, .external) { + --is-icon-hidden: ""; + } - &.download { - @extend %download-link; - } + &.download { + @extend %download-link; + } - &.external { - @extend %external-link; - } + &.external { + @extend %external-link; + } - &.download, - &.external { - &:not([hreflang]) { - --is-lang-hidden: ""; - } + &.download, + &.external { + &:not([hreflang]) { + --is-lang-hidden: ""; } + } - &.external.download { - @extend %external-download-link; - } + &.external.download { + @extend %external-download-link; } } } +} + +.form { + margin-top: var(--spacing-sm); - .footer { - display: flex; - justify-content: flex-end; - align-items: center; - padding: var(--spacing-md) 0 0; + form > * { + margin-inline: auto; } } diff --git a/src/components/organisms/layout/comment.tsx b/src/components/organisms/layout/comment.tsx index cb2f16f..db7cb3a 100644 --- a/src/components/organisms/layout/comment.tsx +++ b/src/components/organisms/layout/comment.tsx @@ -7,7 +7,16 @@ import type { Comment as CommentSchema, WithContext } from 'schema-dts'; import type { SingleComment } from '../../../types'; import { useSettings } from '../../../utils/hooks'; import { Button, Link, Time } from '../../atoms'; -import { MetaList } from '../../molecules'; +import { + Card, + CardActions, + CardBody, + CardCover, + CardFooter, + CardHeader, + CardMeta, + CardTitle, +} from '../../molecules'; import { CommentForm, type CommentFormProps } from '../forms'; import styles from './comment.module.scss'; @@ -103,9 +112,6 @@ export const UserComment: FC = ({ text: content, }; - const commentWrapperClass = `${styles.wrapper} ${styles['wrapper--comment']}`; - const formWrapperClass = `${styles.wrapper} ${styles['wrapper--form']}`; - return ( <>