diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-11-30 19:30:43 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-12-01 16:08:54 +0100 |
| commit | 5b762b1b669454a89899c4bdf6008027d9615acf (patch) | |
| tree | 37087f4ee9d14ae131bde15a48d7d04e83ae6cbd /src/components | |
| parent | f7e6f42216c3cbeab9add475a61bb407c6be3519 (diff) | |
refactor(pages): refine Article pages
* use rehype to update code blocks class names
* fix widget heading level (after a level 1 it should always be a level
2 and not 3)
* replace Spinner with LoadingPage and LoadingPageComments components to
keep layout coherent
* refactor useArticle and useComments hooks
* fix URLs in JSON LD schema
* add Cypress tests
Diffstat (limited to 'src/components')
11 files changed, 156 insertions, 9 deletions
diff --git a/src/components/atoms/links/sharing-link/sharing-link.module.scss b/src/components/atoms/links/sharing-link/sharing-link.module.scss index e1c9c3c..105c37f 100644 --- a/src/components/atoms/links/sharing-link/sharing-link.module.scss +++ b/src/components/atoms/links/sharing-link/sharing-link.module.scss @@ -6,7 +6,7 @@ padding: var(--spacing-2xs) var(--spacing-xs); border-radius: fun.convert-px(3); box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 var(--shadowColor); - transition: all 0.3s linear 0s; + transition: all 0.2s linear 0s; &:hover, &:focus { diff --git a/src/components/organisms/comment/approved-comment/approved-comment.test.tsx b/src/components/organisms/comment/approved-comment/approved-comment.test.tsx index 2e29b5f..b244a63 100644 --- a/src/components/organisms/comment/approved-comment/approved-comment.test.tsx +++ b/src/components/organisms/comment/approved-comment/approved-comment.test.tsx @@ -52,7 +52,9 @@ describe('ApprovedComment', () => { /> ); - expect(rtlScreen.getByRole('img')).toHaveAccessibleName(author.avatar.alt); + expect(rtlScreen.getByRole('figure')).toHaveAccessibleName( + author.avatar.alt + ); }); it('can render a link to the author website', () => { diff --git a/src/components/organisms/comment/approved-comment/approved-comment.tsx b/src/components/organisms/comment/approved-comment/approved-comment.tsx index 233146d..d834ba3 100644 --- a/src/components/organisms/comment/approved-comment/approved-comment.tsx +++ b/src/components/organisms/comment/approved-comment/approved-comment.tsx @@ -117,9 +117,10 @@ const ApprovedCommentWithRef: ForwardRefRenderFunction< className={commentClass} cover={ author.avatar ? ( - <CardCover hasBorders> + <CardCover aria-label={author.avatar.alt} hasBorders> <NextImage - alt={author.avatar.alt} + // eslint-disable-next-line react/jsx-no-literals + alt="" height={96} src={author.avatar.src} width={96} diff --git a/src/components/templates/page/index.ts b/src/components/templates/page/index.ts index f6d2d48..f5330a7 100644 --- a/src/components/templates/page/index.ts +++ b/src/components/templates/page/index.ts @@ -1,3 +1,5 @@ +export * from './loading-page'; +export * from './loading-page-comments'; export * from './page'; export * from './page-body'; export * from './page-comments'; diff --git a/src/components/templates/page/loading-page-comments.stories.tsx b/src/components/templates/page/loading-page-comments.stories.tsx new file mode 100644 index 0000000..6069068 --- /dev/null +++ b/src/components/templates/page/loading-page-comments.stories.tsx @@ -0,0 +1,22 @@ +import type { ComponentMeta, ComponentStory } from '@storybook/react'; +import { LoadingPageComments } from './loading-page-comments'; + +/** + * LoadingPageComments - Storybook Meta + */ +export default { + title: 'Templates/LoadingPageComments', + component: LoadingPageComments, + parameters: { + layout: 'fullscreen', + }, +} as ComponentMeta<typeof LoadingPageComments>; + +const Template: ComponentStory<typeof LoadingPageComments> = (args) => ( + <LoadingPageComments {...args} /> +); + +/** + * LoadingPageComments Stories - Example + */ +export const Example = Template.bind({}); diff --git a/src/components/templates/page/loading-page-comments.test.tsx b/src/components/templates/page/loading-page-comments.test.tsx new file mode 100644 index 0000000..b9ccb3e --- /dev/null +++ b/src/components/templates/page/loading-page-comments.test.tsx @@ -0,0 +1,13 @@ +import { describe, expect, it } from '@jest/globals'; +import { render, screen as rtlScreen } from '../../../../tests/utils'; +import { LoadingPageComments } from './loading-page-comments'; + +describe('LoadingPageComments', () => { + it('renders a spinner', () => { + render(<LoadingPageComments />); + + expect( + rtlScreen.getByText('The comments are loading...') + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/templates/page/loading-page-comments.tsx b/src/components/templates/page/loading-page-comments.tsx new file mode 100644 index 0000000..9235dcb --- /dev/null +++ b/src/components/templates/page/loading-page-comments.tsx @@ -0,0 +1,34 @@ +import { + forwardRef, + type ForwardRefRenderFunction, + type HTMLAttributes, +} from 'react'; +import { useIntl } from 'react-intl'; +import { Spinner } from '../../atoms'; +import styles from './page.module.scss'; + +export type LoadingPageCommentsProps = Omit< + HTMLAttributes<HTMLDivElement>, + 'children' +>; + +const LoadingPageCommentsWithRef: ForwardRefRenderFunction< + HTMLDivElement, + LoadingPageCommentsProps +> = ({ className = '', ...props }, ref) => { + const wrapperClass = `${styles.comments} ${className}`; + const intl = useIntl(); + const loadingMsg = intl.formatMessage({ + defaultMessage: 'The comments are loading...', + description: 'LoadingPageComments: loading message', + id: 'gYbxP4', + }); + + return ( + <div {...props} className={wrapperClass} ref={ref}> + <Spinner className={styles.spinner}>{loadingMsg}</Spinner> + </div> + ); +}; + +export const LoadingPageComments = forwardRef(LoadingPageCommentsWithRef); diff --git a/src/components/templates/page/loading-page.stories.tsx b/src/components/templates/page/loading-page.stories.tsx new file mode 100644 index 0000000..2ea0b33 --- /dev/null +++ b/src/components/templates/page/loading-page.stories.tsx @@ -0,0 +1,22 @@ +import type { ComponentMeta, ComponentStory } from '@storybook/react'; +import { LoadingPage } from './loading-page'; + +/** + * LoadingPage - Storybook Meta + */ +export default { + title: 'Templates/LoadingPage', + component: LoadingPage, + parameters: { + layout: 'fullscreen', + }, +} as ComponentMeta<typeof LoadingPage>; + +const Template: ComponentStory<typeof LoadingPage> = (args) => ( + <LoadingPage {...args} /> +); + +/** + * LoadingPage Stories - Example + */ +export const Example = Template.bind({}); diff --git a/src/components/templates/page/loading-page.test.tsx b/src/components/templates/page/loading-page.test.tsx new file mode 100644 index 0000000..5163943 --- /dev/null +++ b/src/components/templates/page/loading-page.test.tsx @@ -0,0 +1,13 @@ +import { describe, expect, it } from '@jest/globals'; +import { render, screen as rtlScreen } from '../../../../tests/utils'; +import { LoadingPage } from './loading-page'; + +describe('LoadingPage', () => { + it('renders a spinner', () => { + render(<LoadingPage />); + + expect( + rtlScreen.getByText('The requested page is loading...') + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/templates/page/loading-page.tsx b/src/components/templates/page/loading-page.tsx new file mode 100644 index 0000000..18ceed0 --- /dev/null +++ b/src/components/templates/page/loading-page.tsx @@ -0,0 +1,28 @@ +import { forwardRef, type ForwardRefRenderFunction } from 'react'; +import { useIntl } from 'react-intl'; +import { Spinner } from '../../atoms'; +import { Page, type PageProps } from './page'; +import { PageBody } from './page-body'; +import styles from './page.module.scss'; + +const LoadingPageWithRef: ForwardRefRenderFunction< + HTMLDivElement, + Omit<PageProps, 'children'> +> = (props, ref) => { + const intl = useIntl(); + const loadingMsg = intl.formatMessage({ + defaultMessage: 'The requested page is loading...', + description: 'LoadingPage: loading message', + id: '0UzObH', + }); + + return ( + <Page {...props} ref={ref}> + <PageBody> + <Spinner className={styles.spinner}>{loadingMsg}</Spinner> + </PageBody> + </Page> + ); +}; + +export const LoadingPage = forwardRef(LoadingPageWithRef); diff --git a/src/components/templates/page/page.module.scss b/src/components/templates/page/page.module.scss index d2752a1..e7d3587 100644 --- a/src/components/templates/page/page.module.scss +++ b/src/components/templates/page/page.module.scss @@ -18,9 +18,6 @@ .section { --border-size: #{fun.convert-px(3)}; --col-gap: clamp(var(--spacing-md), 4vw, var(--spacing-2xl)); - --left-col: 0; - --right-col: 0; - --main-col: minmax(0, 80ch); @extend %grid; @@ -30,6 +27,10 @@ .breadcrumbs, .page--regular { + --left-col: 0; + --right-col: 0; + --main-col: minmax(0, 1fr); + margin-top: var(--spacing-sm); } @@ -74,7 +75,6 @@ .body { grid-column: 2; - margin-top: var(--spacing-sm); padding-bottom: var(--spacing-md); } @@ -113,8 +113,9 @@ } .section { - --right-col: minmax(0, 1fr); + --main-col: minmax(0, 80ch); --left-col: minmax(0, 1fr); + --right-col: minmax(0, 1fr); @extend %grid; @@ -202,6 +203,10 @@ } } +.spinner { + margin: var(--spacing-lg) auto 0; +} + :where(.comments) { .heading { width: fit-content; @@ -212,11 +217,16 @@ max-width: 40ch; margin-inline: auto; } + + .spinner { + grid-column: 2; + } } @container page (width > #{var.get-breakpoint("md")}) { .breadcrumbs, .page--regular { + --main-col: minmax(0, 80ch); --right-col: minmax(25ch, 1fr); } |
