diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-04-16 16:08:49 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-04-16 16:41:30 +0200 |
| commit | 5a6e4eea16047083e2de0e91a1b3ed9be8d6eb68 (patch) | |
| tree | ea0c5390aca73907aade5321f30cb7bf8d3ab1cb /src/components/organisms | |
| parent | daffe6e8b9e2021ffb9d006482143bc4db985f02 (diff) | |
refactor: support React 18
I replaced the deprecated VFC type with FC type and made all children
explicits.
Formatjs is still not compatible with React 18 so I need to skip type
checking when comitting. There are some type errors because of
IntlProvider in Storybook stories.
Diffstat (limited to 'src/components/organisms')
19 files changed, 129 insertions, 116 deletions
diff --git a/src/components/organisms/forms/comment-form.stories.tsx b/src/components/organisms/forms/comment-form.stories.tsx index 1ab7cf2..670176c 100644 --- a/src/components/organisms/forms/comment-form.stories.tsx +++ b/src/components/organisms/forms/comment-form.stories.tsx @@ -1,4 +1,3 @@ -import Notice from '@components/atoms/layout/notice'; import { ComponentMeta, ComponentStory } from '@storybook/react'; import { IntlProvider } from 'react-intl'; import CommentFormComponent from './comment-form'; diff --git a/src/components/organisms/forms/comment-form.tsx b/src/components/organisms/forms/comment-form.tsx index 6acbf94..d7cb0f5 100644 --- a/src/components/organisms/forms/comment-form.tsx +++ b/src/components/organisms/forms/comment-form.tsx @@ -3,7 +3,7 @@ import Form from '@components/atoms/forms/form'; import Heading, { type HeadingLevel } from '@components/atoms/headings/heading'; import Spinner from '@components/atoms/loaders/spinner'; import LabelledField from '@components/molecules/forms/labelled-field'; -import { ReactNode, useState, VFC } from 'react'; +import { FC, ReactNode, useState } from 'react'; import { useIntl } from 'react-intl'; import styles from './comment-form.module.scss'; @@ -31,7 +31,7 @@ export type CommentFormProps = { titleLevel?: HeadingLevel; }; -const CommentForm: VFC<CommentFormProps> = ({ +const CommentForm: FC<CommentFormProps> = ({ className = '', Notice, saveComment, diff --git a/src/components/organisms/forms/contact-form.tsx b/src/components/organisms/forms/contact-form.tsx index 994244a..4a6902b 100644 --- a/src/components/organisms/forms/contact-form.tsx +++ b/src/components/organisms/forms/contact-form.tsx @@ -2,7 +2,7 @@ import Button from '@components/atoms/buttons/button'; import Form from '@components/atoms/forms/form'; import Spinner from '@components/atoms/loaders/spinner'; import LabelledField from '@components/molecules/forms/labelled-field'; -import { ReactNode, useState, VFC } from 'react'; +import { FC, ReactNode, useState } from 'react'; import { useIntl } from 'react-intl'; import styles from './contact-form.module.scss'; @@ -27,7 +27,7 @@ export type ContactFormProps = { * * Render a contact form. */ -const ContactForm: VFC<ContactFormProps> = ({ +const ContactForm: FC<ContactFormProps> = ({ className = '', Notice, sendMail, diff --git a/src/components/organisms/forms/search-form.tsx b/src/components/organisms/forms/search-form.tsx index 351d93c..18b7c08 100644 --- a/src/components/organisms/forms/search-form.tsx +++ b/src/components/organisms/forms/search-form.tsx @@ -2,15 +2,20 @@ import Button from '@components/atoms/buttons/button'; import Form from '@components/atoms/forms/form'; import MagnifyingGlass from '@components/atoms/icons/magnifying-glass'; import LabelledField, { - LabelledFieldProps, + type LabelledFieldProps, } from '@components/molecules/forms/labelled-field'; -import { useState, VFC } from 'react'; +import { FC, useState } from 'react'; import { useIntl } from 'react-intl'; import styles from './search-form.module.scss'; export type SearchFormProps = Pick<LabelledFieldProps, 'hideLabel'>; -const SearchForm: VFC<SearchFormProps> = ({ hideLabel }) => { +/** + * SearchForm component + * + * Render a search form. + */ +const SearchForm: FC<SearchFormProps> = ({ hideLabel }) => { const intl = useIntl(); const fieldLabel = intl.formatMessage({ defaultMessage: 'Search for:', diff --git a/src/components/organisms/layout/cards-list.tsx b/src/components/organisms/layout/cards-list.tsx index a53df0d..33ffe23 100644 --- a/src/components/organisms/layout/cards-list.tsx +++ b/src/components/organisms/layout/cards-list.tsx @@ -3,7 +3,7 @@ import List, { type ListProps, } from '@components/atoms/lists/list'; import Card, { type CardProps } from '@components/molecules/layout/card'; -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './cards-list.module.scss'; export type CardsListItem = Omit< @@ -37,7 +37,7 @@ export type CardsListProps = { * * Return a list of Card components. */ -const CardsList: VFC<CardsListProps> = ({ +const CardsList: FC<CardsListProps> = ({ coverFit, items, kind = 'unordered', diff --git a/src/components/organisms/layout/footer.tsx b/src/components/organisms/layout/footer.tsx index c9cb067..15bfa24 100644 --- a/src/components/organisms/layout/footer.tsx +++ b/src/components/organisms/layout/footer.tsx @@ -1,7 +1,9 @@ -import Copyright, { CopyrightProps } from '@components/atoms/layout/copyright'; +import Copyright, { + type CopyrightProps, +} from '@components/atoms/layout/copyright'; import BackToTop from '@components/molecules/buttons/back-to-top'; import Nav, { type NavItem } from '@components/molecules/nav/nav'; -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './footer.module.scss'; export type FooterProps = { @@ -28,12 +30,7 @@ export type FooterProps = { * * Renders a footer with copyright and nav; */ -const Footer: VFC<FooterProps> = ({ - className, - copyright, - navItems, - topId, -}) => { +const Footer: FC<FooterProps> = ({ className, copyright, navItems, topId }) => { return ( <footer className={`${styles.wrapper} ${className}`}> <Copyright diff --git a/src/components/organisms/layout/overview.tsx b/src/components/organisms/layout/overview.tsx index 3f83342..42d0431 100644 --- a/src/components/organisms/layout/overview.tsx +++ b/src/components/organisms/layout/overview.tsx @@ -2,7 +2,7 @@ import ResponsiveImage, { type ResponsiveImageProps, } from '@components/molecules/images/responsive-image'; import Meta, { type MetaMap } from '@components/molecules/layout/meta'; -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './overview.module.scss'; export type OverviewProps = { @@ -15,7 +15,7 @@ export type OverviewProps = { * * Render an overview. */ -const Overview: VFC<OverviewProps> = ({ cover, meta }) => { +const Overview: FC<OverviewProps> = ({ cover, meta }) => { return ( <div className={styles.wrapper}> {cover && ( diff --git a/src/components/organisms/layout/summary.stories.tsx b/src/components/organisms/layout/summary.stories.tsx index 5214d70..b33acde 100644 --- a/src/components/organisms/layout/summary.stories.tsx +++ b/src/components/organisms/layout/summary.stories.tsx @@ -103,7 +103,7 @@ Summary.args = { cover: { alt: 'A cover', height: 480, - url: 'http://placeimg.com/640/480', + src: 'http://placeimg.com/640/480', width: 640, }, excerpt: diff --git a/src/components/organisms/layout/summary.test.tsx b/src/components/organisms/layout/summary.test.tsx index ce87c0c..4944805 100644 --- a/src/components/organisms/layout/summary.test.tsx +++ b/src/components/organisms/layout/summary.test.tsx @@ -4,7 +4,7 @@ import Summary from './summary'; const cover = { alt: 'A cover', height: 480, - url: 'http://placeimg.com/640/480', + src: 'http://placeimg.com/640/480', width: 640, }; diff --git a/src/components/organisms/layout/summary.tsx b/src/components/organisms/layout/summary.tsx index 3624e5d..733a660 100644 --- a/src/components/organisms/layout/summary.tsx +++ b/src/components/organisms/layout/summary.tsx @@ -2,18 +2,18 @@ import ButtonLink from '@components/atoms/buttons/button-link'; import Heading, { type HeadingLevel } from '@components/atoms/headings/heading'; import Arrow from '@components/atoms/icons/arrow'; import Link from '@components/atoms/links/link'; -import ResponsiveImage from '@components/molecules/images/responsive-image'; +import ResponsiveImage, { + type ResponsiveImageProps, +} from '@components/molecules/images/responsive-image'; import Meta, { type MetaItem } from '@components/molecules/layout/meta'; -import { VFC } from 'react'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; import styles from './summary.module.scss'; -export type Cover = { - alt: string; - height: number; - url: string; - width: number; -}; +export type Cover = Pick< + ResponsiveImageProps, + 'alt' | 'src' | 'width' | 'height' +>; export type RequiredMetaKey = 'publication'; @@ -35,11 +35,29 @@ export type OptionalMeta = { export type Meta = RequiredMeta & OptionalMeta; export type SummaryProps = { + /** + * The post cover. + */ cover?: Cover; + /** + * The post excerpt. + */ excerpt: string; + /** + * The post meta. + */ meta: Meta; + /** + * The post title. + */ title: string; + /** + * The heading level (hn). + */ titleLevel?: HeadingLevel; + /** + * The post url. + */ url: string; }; @@ -48,7 +66,7 @@ export type SummaryProps = { * * Render a page summary. */ -const Summary: VFC<SummaryProps> = ({ +const Summary: FC<SummaryProps> = ({ cover, excerpt, meta, @@ -57,18 +75,23 @@ const Summary: VFC<SummaryProps> = ({ url, }) => { const intl = useIntl(); + const readMore = intl.formatMessage( + { + defaultMessage: 'Read more<a11y> about {title}</a11y>', + description: 'Summary: read more link', + id: 'Zpgv+f', + }, + { + title, + a11y: (chunks: string) => ( + <span className="screen-reader-text">{chunks}</span> + ), + } + ); return ( <article className={styles.wrapper}> - {cover && ( - <ResponsiveImage - alt={cover.alt} - src={cover.url} - width={cover.width} - height={cover.height} - className={styles.cover} - /> - )} + {cover && <ResponsiveImage className={styles.cover} {...cover} />} <header className={styles.header}> <Link href={url}> <Heading level={titleLevel} className={styles.title}> @@ -79,20 +102,10 @@ const Summary: VFC<SummaryProps> = ({ <div className={styles.body}> {excerpt} <ButtonLink target={url} className={styles['read-more']}> - {intl.formatMessage( - { - defaultMessage: 'Read more<a11y> about {title}</a11y>', - description: 'Summary: read more link', - id: 'Zpgv+f', - }, - { - title, - a11y: (chunks: string) => ( - <span className="screen-reader-text">{chunks}</span> - ), - } - )} - <Arrow direction="right" /> + <> + {readMore} + <Arrow direction="right" /> + </> </ButtonLink> </div> <footer className={styles.footer}> diff --git a/src/components/organisms/modals/search-modal.tsx b/src/components/organisms/modals/search-modal.tsx index 883b783..0e0ceed 100644 --- a/src/components/organisms/modals/search-modal.tsx +++ b/src/components/organisms/modals/search-modal.tsx @@ -1,5 +1,5 @@ -import Modal from '@components/molecules/modals/modal'; -import { VFC } from 'react'; +import Modal, { type ModalProps } from '@components/molecules/modals/modal'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; import SearchForm from '../forms/search-form'; import styles from './search-modal.module.scss'; @@ -8,7 +8,7 @@ export type SearchModalProps = { /** * Set additional classnames to modal wrapper. */ - className?: string; + className?: ModalProps['className']; }; /** @@ -16,7 +16,7 @@ export type SearchModalProps = { * * Render a search form modal. */ -const SearchModal: VFC<SearchModalProps> = ({ className }) => { +const SearchModal: FC<SearchModalProps> = ({ className }) => { const intl = useIntl(); const modalTitle = intl.formatMessage({ defaultMessage: 'Search', diff --git a/src/components/organisms/modals/settings-modal.tsx b/src/components/organisms/modals/settings-modal.tsx index 25d6f6f..20d2605 100644 --- a/src/components/organisms/modals/settings-modal.tsx +++ b/src/components/organisms/modals/settings-modal.tsx @@ -1,10 +1,12 @@ import Form from '@components/atoms/forms/form'; -import AckeeSelect from '@components/molecules/forms/ackee-select'; +import AckeeSelect, { + type AckeeSelectProps, +} from '@components/molecules/forms/ackee-select'; import MotionToggle from '@components/molecules/forms/motion-toggle'; import PrismThemeToggle from '@components/molecules/forms/prism-theme-toggle'; import ThemeToggle from '@components/molecules/forms/theme-toggle'; -import Modal from '@components/molecules/modals/modal'; -import { VFC } from 'react'; +import Modal, { type ModalProps } from '@components/molecules/modals/modal'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; import styles from './settings-modal.module.scss'; @@ -12,11 +14,11 @@ export type SettingsModalProps = { /** * Set additional classnames to the modal wrapper. */ - className?: string; + className?: ModalProps['className']; /** * Set additional classnames to the tooltip wrapper. */ - tooltipClassName?: string; + tooltipClassName?: AckeeSelectProps['tooltipClassName']; }; /** @@ -24,7 +26,7 @@ export type SettingsModalProps = { * * Render a modal with settings options. */ -const SettingsModal: VFC<SettingsModalProps> = ({ +const SettingsModal: FC<SettingsModalProps> = ({ className = '', tooltipClassName = '', }) => { diff --git a/src/components/organisms/toolbar/main-nav.tsx b/src/components/organisms/toolbar/main-nav.tsx index 50bbe8b..35e3fd6 100644 --- a/src/components/organisms/toolbar/main-nav.tsx +++ b/src/components/organisms/toolbar/main-nav.tsx @@ -1,17 +1,20 @@ import Checkbox, { type CheckboxProps } from '@components/atoms/forms/checkbox'; import Label from '@components/atoms/forms/label'; import Hamburger from '@components/atoms/icons/hamburger'; -import Nav, { type NavItem } from '@components/molecules/nav/nav'; -import { VFC } from 'react'; +import Nav, { + type NavProps, + type NavItem, +} from '@components/molecules/nav/nav'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; -import sharedStyles from './toolbar-items.module.scss'; import mainNavStyles from './main-nav.module.scss'; +import sharedStyles from './toolbar-items.module.scss'; export type MainNavProps = { /** * Set additional classnames to the nav element. */ - className?: string; + className?: NavProps['className']; /** * The button state. */ @@ -26,7 +29,12 @@ export type MainNavProps = { setIsActive: CheckboxProps['setValue']; }; -const MainNav: VFC<MainNavProps> = ({ +/** + * MainNav component + * + * Render the main navigation. + */ +const MainNav: FC<MainNavProps> = ({ className = '', isActive, items, diff --git a/src/components/organisms/toolbar/search.tsx b/src/components/organisms/toolbar/search.tsx index 070bce0..72cd576 100644 --- a/src/components/organisms/toolbar/search.tsx +++ b/src/components/organisms/toolbar/search.tsx @@ -1,17 +1,17 @@ -import Checkbox, { CheckboxProps } from '@components/atoms/forms/checkbox'; +import Checkbox, { type CheckboxProps } from '@components/atoms/forms/checkbox'; import Label from '@components/atoms/forms/label'; import MagnifyingGlass from '@components/atoms/icons/magnifying-glass'; -import { VFC } from 'react'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; -import SearchModal from '../modals/search-modal'; -import sharedStyles from './toolbar-items.module.scss'; +import SearchModal, { type SearchModalProps } from '../modals/search-modal'; import searchStyles from './search.module.scss'; +import sharedStyles from './toolbar-items.module.scss'; export type SearchProps = { /** * Set additional classnames to the modal wrapper. */ - className?: string; + className?: SearchModalProps['className']; /** * The button state. */ @@ -22,11 +22,7 @@ export type SearchProps = { setIsActive: CheckboxProps['setValue']; }; -const Search: VFC<SearchProps> = ({ - className = '', - isActive, - setIsActive, -}) => { +const Search: FC<SearchProps> = ({ className = '', isActive, setIsActive }) => { const intl = useIntl(); const label = isActive ? intl.formatMessage({ diff --git a/src/components/organisms/toolbar/settings.tsx b/src/components/organisms/toolbar/settings.tsx index 88539fb..3b10226 100644 --- a/src/components/organisms/toolbar/settings.tsx +++ b/src/components/organisms/toolbar/settings.tsx @@ -1,11 +1,13 @@ -import Checkbox, { CheckboxProps } from '@components/atoms/forms/checkbox'; +import Checkbox, { type CheckboxProps } from '@components/atoms/forms/checkbox'; import Label from '@components/atoms/forms/label'; import Cog from '@components/atoms/icons/cog'; -import { VFC } from 'react'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; -import SettingsModal from '../modals/settings-modal'; -import sharedStyles from './toolbar-items.module.scss'; +import SettingsModal, { + type SettingsModalProps, +} from '../modals/settings-modal'; import settingsStyles from './settings.module.scss'; +import sharedStyles from './toolbar-items.module.scss'; export type SettingsProps = { /** @@ -23,10 +25,10 @@ export type SettingsProps = { /** * Set additional classnames to the tooltip wrapper. */ - tooltipClassName?: string; + tooltipClassName?: SettingsModalProps['tooltipClassName']; }; -const Settings: VFC<SettingsProps> = ({ +const Settings: FC<SettingsProps> = ({ className = '', isActive, setIsActive, diff --git a/src/components/organisms/toolbar/toolbar.tsx b/src/components/organisms/toolbar/toolbar.tsx index 81e80cf..f1ce530 100644 --- a/src/components/organisms/toolbar/toolbar.tsx +++ b/src/components/organisms/toolbar/toolbar.tsx @@ -1,4 +1,4 @@ -import { useState, VFC } from 'react'; +import { FC, useState } from 'react'; import MainNav, { type MainNavProps } from '../toolbar/main-nav'; import Search from '../toolbar/search'; import Settings from '../toolbar/settings'; @@ -20,7 +20,7 @@ export type ToolbarProps = { * * Render the website toolbar. */ -const Toolbar: VFC<ToolbarProps> = ({ className = '', nav }) => { +const Toolbar: FC<ToolbarProps> = ({ className = '', nav }) => { const [isNavOpened, setIsNavOpened] = useState<boolean>(false); const [isSettingsOpened, setIsSettingsOpened] = useState<boolean>(false); const [isSearchOpened, setIsSearchOpened] = useState<boolean>(false); diff --git a/src/components/organisms/widgets/image-widget.tsx b/src/components/organisms/widgets/image-widget.tsx index 928d5ea..ba04c6a 100644 --- a/src/components/organisms/widgets/image-widget.tsx +++ b/src/components/organisms/widgets/image-widget.tsx @@ -1,28 +1,16 @@ -import ResponsiveImage from '@components/molecules/images/responsive-image'; +import ResponsiveImage, { + type ResponsiveImageProps, +} from '@components/molecules/images/responsive-image'; import Widget, { type WidgetProps } from '@components/molecules/layout/widget'; -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './image-widget.module.scss'; export type Alignment = 'left' | 'center' | 'right'; -export type Image = { - /** - * An alternative text for the image. - */ - alt: string; - /** - * The image height. - */ - height: number; - /** - * The image source. - */ - src: string; - /** - * The image width. - */ - width: number; -}; +export type Image = Pick< + ResponsiveImageProps, + 'alt' | 'height' | 'src' | 'width' +>; export type ImageWidgetProps = Pick< WidgetProps, @@ -35,7 +23,7 @@ export type ImageWidgetProps = Pick< /** * Add a caption to the image. */ - description?: string; + description?: ResponsiveImageProps['caption']; /** * An object describing the image. */ @@ -43,7 +31,7 @@ export type ImageWidgetProps = Pick< /** * Add a link to the image. */ - url?: string; + url?: ResponsiveImageProps['target']; }; /** @@ -51,7 +39,7 @@ export type ImageWidgetProps = Pick< * * Renders a widget that print an image and an optional text. */ -const ImageWidget: VFC<ImageWidgetProps> = ({ +const ImageWidget: FC<ImageWidgetProps> = ({ alignment = 'left', description, img, diff --git a/src/components/organisms/widgets/links-list-widget.tsx b/src/components/organisms/widgets/links-list-widget.tsx index 155354e..559d0b6 100644 --- a/src/components/organisms/widgets/links-list-widget.tsx +++ b/src/components/organisms/widgets/links-list-widget.tsx @@ -1,8 +1,11 @@ import Link from '@components/atoms/links/link'; -import List, { ListProps, type ListItem } from '@components/atoms/lists/list'; +import List, { + type ListProps, + type ListItem, +} from '@components/atoms/lists/list'; import Widget, { type WidgetProps } from '@components/molecules/layout/widget'; import { slugify } from '@utils/helpers/slugify'; -import { VFC } from 'react'; +import { FC } from 'react'; import styles from './links-list-widget.module.scss'; export type LinksListItems = { @@ -33,7 +36,7 @@ export type LinksListWidgetProps = Pick<WidgetProps, 'level' | 'title'> & * * Render a list of links inside a widget. */ -const LinksListWidget: VFC<LinksListWidgetProps> = ({ +const LinksListWidget: FC<LinksListWidgetProps> = ({ items, kind = 'unordered', ...props diff --git a/src/components/organisms/widgets/sharing.tsx b/src/components/organisms/widgets/sharing.tsx index ccd3a21..571c1a4 100644 --- a/src/components/organisms/widgets/sharing.tsx +++ b/src/components/organisms/widgets/sharing.tsx @@ -2,7 +2,7 @@ import SharingLink, { type SharingMedium, } from '@components/atoms/links/sharing-link'; import Widget, { type WidgetProps } from '@components/molecules/layout/widget'; -import { VFC } from 'react'; +import { FC } from 'react'; import { useIntl } from 'react-intl'; import styles from './sharing.module.scss'; @@ -21,7 +21,7 @@ export type SharingData = { url: string; }; -export type SharingProps = WidgetProps & { +export type SharingProps = Omit<WidgetProps, 'children'> & { /** * The page data to share. */ @@ -37,7 +37,7 @@ export type SharingProps = WidgetProps & { * * Render a list of sharing links inside a widget. */ -const Sharing: VFC<SharingProps> = ({ data, media, ...props }) => { +const Sharing: FC<SharingProps> = ({ data, media, ...props }) => { const intl = useIntl(); /** |
