From 15522ec9146f6f1956620355c44dea2a6a75b67c Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Mon, 9 Oct 2023 18:26:23 +0200 Subject: refactor(components): replace ResponsiveImage with Figure component The styles applied to ResponsiveImage are related to the figure and figcaption elements. Those elements could be use with other contents than images. So I extracted them in a Figure component. The ResponsiveImage component is no longer useful: the consumer should use the Image component from `next` and wrap it in a link if needed. --- src/components/molecules/images/index.ts | 1 - .../molecules/images/responsive-image.module.scss | 84 -------- .../molecules/images/responsive-image.stories.tsx | 212 --------------------- .../molecules/images/responsive-image.test.tsx | 19 -- .../molecules/images/responsive-image.tsx | 91 --------- src/components/molecules/layout/card.fixture.ts | 19 ++ src/components/molecules/layout/card.fixture.tsx | 19 -- src/components/molecules/layout/card.module.scss | 1 + src/components/molecules/layout/card.tsx | 11 +- 9 files changed, 26 insertions(+), 431 deletions(-) delete mode 100644 src/components/molecules/images/responsive-image.module.scss delete mode 100644 src/components/molecules/images/responsive-image.stories.tsx delete mode 100644 src/components/molecules/images/responsive-image.test.tsx delete mode 100644 src/components/molecules/images/responsive-image.tsx create mode 100644 src/components/molecules/layout/card.fixture.ts delete mode 100644 src/components/molecules/layout/card.fixture.tsx (limited to 'src/components/molecules') diff --git a/src/components/molecules/images/index.ts b/src/components/molecules/images/index.ts index 33ec886..318a6af 100644 --- a/src/components/molecules/images/index.ts +++ b/src/components/molecules/images/index.ts @@ -1,2 +1 @@ export * from './flipping-logo'; -export * from './responsive-image'; diff --git a/src/components/molecules/images/responsive-image.module.scss b/src/components/molecules/images/responsive-image.module.scss deleted file mode 100644 index e4ed4aa..0000000 --- a/src/components/molecules/images/responsive-image.module.scss +++ /dev/null @@ -1,84 +0,0 @@ -@use "../../../styles/abstracts/functions" as fun; - -.caption { - margin: 0; - padding: fun.convert-px(4) var(--spacing-2xs); - background: var(--color-bg-secondary); - border: fun.convert-px(1) solid var(--color-border-light); - font-size: var(--font-size-sm); - font-weight: 500; -} - -.wrapper { - display: flex; - flex-flow: column; - width: fit-content; - margin: 0 auto; - position: relative; - text-align: center; - - &--has-borders { - .caption { - margin-top: fun.convert-px(4); - } - } - - &--has-borders#{&}--has-link { - .link { - padding: fun.convert-px(4); - } - } - - &--has-borders#{&}--no-link { - padding: fun.convert-px(4); - border: fun.convert-px(1) solid var(--color-border); - box-shadow: fun.convert-px(1) fun.convert-px(1) fun.convert-px(1) 0 - var(--color-shadow); - } -} - -.img { - max-height: 100%; - object-fit: cover; -} - -.link { - display: flex; - flex-flow: column; - background: none; - border: fun.convert-px(1) solid var(--color-border); - box-shadow: fun.convert-px(1) fun.convert-px(1) fun.convert-px(1) 0 - var(--color-shadow); - text-decoration: none; - - .caption { - color: var(--color-primary-darker); - } - - &:hover, - &:focus { - box-shadow: 0 0 fun.convert-px(2) 0 var(--color-shadow-light), - fun.convert-px(2) fun.convert-px(2) fun.convert-px(4) fun.convert-px(1) - var(--color-shadow-light), - fun.convert-px(4) fun.convert-px(4) fun.convert-px(8) fun.convert-px(2) - var(--color-shadow-light); - transform: scale(var(--scale-up, 1.05)); - } - - &:focus { - .caption { - text-decoration: underline solid var(--color-primary-darker) - fun.convert-px(3); - } - } - - &:active { - box-shadow: fun.convert-px(1) fun.convert-px(1) fun.convert-px(1) - fun.convert-px(1) var(--color-shadow-light); - transform: scale(var(--scale-down, 0.95)); - - .caption { - text-decoration: none; - } - } -} diff --git a/src/components/molecules/images/responsive-image.stories.tsx b/src/components/molecules/images/responsive-image.stories.tsx deleted file mode 100644 index cc6b088..0000000 --- a/src/components/molecules/images/responsive-image.stories.tsx +++ /dev/null @@ -1,212 +0,0 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { ResponsiveImage } from './responsive-image'; - -/** - * ResponsiveImage - Storybook Meta - */ -export default { - title: 'Molecules/Images/ResponsiveImage', - component: ResponsiveImage, - args: { - withBorders: false, - }, - argTypes: { - alt: { - control: { - type: 'text', - }, - description: 'An alternative text.', - type: { - name: 'string', - required: true, - }, - }, - caption: { - control: { - type: 'text', - }, - description: 'A figure caption.', - table: { - category: 'Options', - }, - type: { - name: 'string', - required: false, - }, - }, - className: { - control: { - type: 'text', - }, - description: 'Set additional classnames to the image wrapper.', - table: { - category: 'Styles', - }, - type: { - name: 'string', - required: false, - }, - }, - height: { - control: { - type: 'number', - }, - description: 'The image height.', - type: { - name: 'string', - required: true, - }, - }, - src: { - control: { - type: 'text', - }, - description: 'The image source.', - type: { - name: 'string', - required: true, - }, - }, - target: { - control: { - type: 'text', - }, - description: 'A link target.', - table: { - category: 'Options', - }, - type: { - name: 'string', - required: false, - }, - }, - width: { - control: { - type: 'number', - }, - description: 'The image width.', - type: { - name: 'string', - required: true, - }, - }, - withBorders: { - control: { - type: 'boolean', - }, - description: 'Add borders around the image.', - table: { - category: 'Styles', - defaultValue: { summary: false }, - }, - type: { - name: 'boolean', - required: false, - }, - }, - }, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ( - -); - -/** - * Responsive Image Stories - Default - */ -export const Default = Template.bind({}); -Default.args = { - alt: 'An example', - src: 'http://placeimg.com/640/480/transport', - width: 640, - height: 480, -}; - -/** - * Responsive Image Stories - With borders - */ -export const WithBorders = Template.bind({}); -WithBorders.args = { - alt: 'An example', - src: 'http://placeimg.com/640/480/transport', - width: 640, - height: 480, - withBorders: true, -}; - -/** - * Responsive Image Stories - With link - */ -export const WithLink = Template.bind({}); -WithLink.args = { - alt: 'An example', - src: 'http://placeimg.com/640/480/transport', - width: 640, - height: 480, - target: '#', -}; - -/** - * Responsive Image Stories - With link and borders - */ -export const WithLinkAndBorders = Template.bind({}); -WithLinkAndBorders.args = { - alt: 'An example', - src: 'http://placeimg.com/640/480/transport', - width: 640, - height: 480, - target: '#', - withBorders: true, -}; - -/** - * Responsive Image Stories - With caption - */ -export const WithCaption = Template.bind({}); -WithCaption.args = { - alt: 'An example', - src: 'http://placeimg.com/640/480/transport', - width: 640, - height: 480, - caption: 'Omnis nulla labore', -}; - -/** - * Responsive Image Stories - With caption and borders - */ -export const WithCaptionAndBorders = Template.bind({}); -WithCaptionAndBorders.args = { - alt: 'An example', - src: 'http://placeimg.com/640/480/transport', - width: 640, - height: 480, - caption: 'Omnis nulla labore', - withBorders: true, -}; - -/** - * Responsive Image Stories - With caption and link - */ -export const WithCaptionAndLink = Template.bind({}); -WithCaptionAndLink.args = { - alt: 'An example', - src: 'http://placeimg.com/640/480/transport', - width: 640, - height: 480, - caption: 'Omnis nulla labore', - target: '#', -}; - -/** - * Responsive Image Stories - With caption, link and borders - */ -export const WithCaptionLinkAndBorders = Template.bind({}); -WithCaptionLinkAndBorders.args = { - alt: 'An example', - src: 'http://placeimg.com/640/480/transport', - width: 640, - height: 480, - caption: 'Omnis nulla labore', - target: '#', - withBorders: true, -}; diff --git a/src/components/molecules/images/responsive-image.test.tsx b/src/components/molecules/images/responsive-image.test.tsx deleted file mode 100644 index dec36ea..0000000 --- a/src/components/molecules/images/responsive-image.test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { describe, expect, it } from '@jest/globals'; -import { render, screen } from '../../../../tests/utils'; -import { ResponsiveImage } from './responsive-image'; - -describe('ResponsiveImage', () => { - it('renders a responsive image', () => { - render( - - ); - expect( - screen.getByRole('img', { name: 'An alternative text' }) - ).toBeInTheDocument(); - }); -}); diff --git a/src/components/molecules/images/responsive-image.tsx b/src/components/molecules/images/responsive-image.tsx deleted file mode 100644 index 85c0c46..0000000 --- a/src/components/molecules/images/responsive-image.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import Image, { type ImageProps } from 'next/image'; -import { FC, ReactNode } from 'react'; -import { Link, type LinkProps } from '../../atoms'; -import styles from './responsive-image.module.scss'; - -export type ResponsiveImageProps = Omit< - ImageProps, - 'alt' | 'width' | 'height' -> & { - /** - * An alternative text. - */ - alt: string; - /** - * A figure caption. - */ - caption?: ReactNode; - /** - * Set additional classnames to the figure wrapper. - */ - className?: string; - /** - * The image height. - */ - height: number | `${number}`; - /** - * A link target. - */ - target?: LinkProps['href']; - /** - * The image width. - */ - width: number | `${number}`; - /** - * Wrap the image with borders. - */ - withBorders?: boolean; -}; - -/** - * ResponsiveImage component - * - * Render a responsive image wrapped in a figure element. - */ -export const ResponsiveImage: FC = ({ - alt, - caption, - className = '', - target, - title, - withBorders, - ...props -}) => { - const bordersModifier = withBorders ? styles['wrapper--has-borders'] : ''; - const linkModifier = target - ? styles['wrapper--has-link'] - : styles['wrapper--no-link']; - const figureClass = `${styles.wrapper} ${bordersModifier} ${linkModifier} ${className}`; - - return ( -
- {target ? ( - - {alt} - {caption && ( -
{caption}
- )} - - ) : ( - <> - {alt} - {caption && ( -
{caption}
- )} - - )} -
- ); -}; diff --git a/src/components/molecules/layout/card.fixture.ts b/src/components/molecules/layout/card.fixture.ts new file mode 100644 index 0000000..01fe2e9 --- /dev/null +++ b/src/components/molecules/layout/card.fixture.ts @@ -0,0 +1,19 @@ +export const cover = { + alt: 'A picture', + height: 480, + src: 'https://picsum.photos/640/480', + width: 640, +}; + +export const id = 'nam'; + +export const meta = { + author: 'Possimus', + thematics: ['Autem', 'Eos'], +}; + +export const tagline = 'Ut rerum incidunt'; + +export const title = 'Alias qui porro'; + +export const url = '/an-existing-url'; diff --git a/src/components/molecules/layout/card.fixture.tsx b/src/components/molecules/layout/card.fixture.tsx deleted file mode 100644 index f96cc43..0000000 --- a/src/components/molecules/layout/card.fixture.tsx +++ /dev/null @@ -1,19 +0,0 @@ -export const cover = { - alt: 'A picture', - height: 480, - src: 'http://placeimg.com/640/480', - width: 640, -}; - -export const id = 'nam'; - -export const meta = { - author: 'Possimus', - thematics: ['Autem', 'Eos'], -}; - -export const tagline = 'Ut rerum incidunt'; - -export const title = 'Alias qui porro'; - -export const url = '/an-existing-url'; diff --git a/src/components/molecules/layout/card.module.scss b/src/components/molecules/layout/card.module.scss index 31f6a4b..7a06508 100644 --- a/src/components/molecules/layout/card.module.scss +++ b/src/components/molecules/layout/card.module.scss @@ -20,6 +20,7 @@ .cover { place-content: center; height: fun.convert-px(150); + object-fit: scale-down; margin: auto; border-bottom: fun.convert-px(1) solid var(--color-border); } diff --git a/src/components/molecules/layout/card.tsx b/src/components/molecules/layout/card.tsx index c9e7a90..c316100 100644 --- a/src/components/molecules/layout/card.tsx +++ b/src/components/molecules/layout/card.tsx @@ -1,7 +1,6 @@ +import NextImage, { type ImageProps as NextImageProps } from 'next/image'; import type { FC } from 'react'; -import type { Image as Img } from '../../../types'; -import { ButtonLink, Heading, type HeadingLevel } from '../../atoms'; -import { ResponsiveImage } from '../images'; +import { ButtonLink, Figure, Heading, type HeadingLevel } from '../../atoms'; import styles from './card.module.scss'; import { Meta, type MetaData } from './meta'; @@ -13,7 +12,7 @@ export type CardProps = { /** * The card cover. */ - cover?: Img; + cover?: Pick; /** * The card id. */ @@ -63,7 +62,9 @@ export const Card: FC = ({
{cover ? ( - +
+ +
) : null} {title} -- cgit v1.2.3