From 50f1c501a87ef5f5650750dbeca797e833ec7c3a Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Tue, 14 Nov 2023 12:39:09 +0100 Subject: refactor(components): replace Sharing with SharingWidget component * all the widgets should have a coherent name * fix mailto uri * remove useless CSS * add tests --- src/components/organisms/widgets/index.ts | 2 +- .../organisms/widgets/sharing-widget/index.ts | 1 + .../sharing-widget/sharing-widget.stories.tsx | 50 ++++ .../widgets/sharing-widget/sharing-widget.test.tsx | 167 +++++++++++++ .../widgets/sharing-widget/sharing-widget.tsx | 161 +++++++++++++ .../organisms/widgets/sharing.module.scss | 8 - .../organisms/widgets/sharing.stories.tsx | 61 ----- src/components/organisms/widgets/sharing.test.tsx | 24 -- src/components/organisms/widgets/sharing.tsx | 259 --------------------- .../templates/page/page-layout.stories.tsx | 8 +- src/i18n/en.json | 74 +++--- src/i18n/fr.json | 74 +++--- src/pages/article/[slug].tsx | 11 +- src/pages/projets/[slug].tsx | 10 +- src/styles/pages/article.module.scss | 5 +- 15 files changed, 475 insertions(+), 440 deletions(-) create mode 100644 src/components/organisms/widgets/sharing-widget/index.ts create mode 100644 src/components/organisms/widgets/sharing-widget/sharing-widget.stories.tsx create mode 100644 src/components/organisms/widgets/sharing-widget/sharing-widget.test.tsx create mode 100644 src/components/organisms/widgets/sharing-widget/sharing-widget.tsx delete mode 100644 src/components/organisms/widgets/sharing.module.scss delete mode 100644 src/components/organisms/widgets/sharing.stories.tsx delete mode 100644 src/components/organisms/widgets/sharing.test.tsx delete mode 100644 src/components/organisms/widgets/sharing.tsx (limited to 'src') diff --git a/src/components/organisms/widgets/index.ts b/src/components/organisms/widgets/index.ts index 03f845f..2286898 100644 --- a/src/components/organisms/widgets/index.ts +++ b/src/components/organisms/widgets/index.ts @@ -1,5 +1,5 @@ export * from './image-widget'; export * from './links-list-widget'; -export * from './sharing'; +export * from './sharing-widget'; export * from './social-media-widget'; export * from './table-of-contents'; diff --git a/src/components/organisms/widgets/sharing-widget/index.ts b/src/components/organisms/widgets/sharing-widget/index.ts new file mode 100644 index 0000000..dd78023 --- /dev/null +++ b/src/components/organisms/widgets/sharing-widget/index.ts @@ -0,0 +1 @@ +export * from './sharing-widget'; diff --git a/src/components/organisms/widgets/sharing-widget/sharing-widget.stories.tsx b/src/components/organisms/widgets/sharing-widget/sharing-widget.stories.tsx new file mode 100644 index 0000000..3e3cb68 --- /dev/null +++ b/src/components/organisms/widgets/sharing-widget/sharing-widget.stories.tsx @@ -0,0 +1,50 @@ +import type { ComponentMeta, ComponentStory } from '@storybook/react'; +import { Heading } from '../../../atoms'; +import { SharingWidget } from './sharing-widget'; + +/** + * SharingWidget - Storybook Meta + */ +export default { + title: 'Organisms/Widgets/Sharing', + component: SharingWidget, + argTypes: { + data: { + description: 'The page data.', + type: { + name: 'object', + required: true, + value: {}, + }, + }, + media: { + control: { + type: null, + }, + description: 'An array of active and ordered sharing medium.', + type: { + name: 'string', + required: true, + }, + }, + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +/** + * SharingWidget Stories - Sharing + */ +export const Sharing = Template.bind({}); +Sharing.args = { + data: { + excerpt: + 'Alias similique eius ducimus laudantium aspernatur. Est rem ut eum temporibus sit reprehenderit aut non molestias. Vel dolorem expedita labore quo inventore aliquid nihil nam. Possimus nobis enim quas corporis eos.', + title: 'Accusantium totam nostrum', + url: 'https://www.example.test', + }, + heading: Share, + media: ['diaspora', 'facebook', 'linkedin', 'twitter', 'email'], +}; diff --git a/src/components/organisms/widgets/sharing-widget/sharing-widget.test.tsx b/src/components/organisms/widgets/sharing-widget/sharing-widget.test.tsx new file mode 100644 index 0000000..b8bc702 --- /dev/null +++ b/src/components/organisms/widgets/sharing-widget/sharing-widget.test.tsx @@ -0,0 +1,167 @@ +import { describe, expect, it } from '@jest/globals'; +import { render, screen as rtlScreen } from '../../../../../tests/utils'; +import { Heading, type SharingMedium } from '../../../atoms'; +import { SharingWidget, type SharingData } from './sharing-widget'; + +const data: SharingData = { + excerpt: 'A post excerpt', + title: 'A post title', + url: 'https://sharing-website.test', +}; + +describe('SharingWidget', () => { + it('renders the widget heading and a list of links', () => { + const heading = 'dolorem necessitatibus voluptatem'; + const headingLvl = 3; + const media = ['facebook', 'twitter'] satisfies SharingMedium[]; + + render( + {heading}} + media={media} + /> + ); + + expect( + rtlScreen.getByRole('heading', { level: headingLvl }) + ).toHaveTextContent(heading); + expect(rtlScreen.getAllByRole('listitem')).toHaveLength(media.length); + expect(rtlScreen.getAllByRole('link')).toHaveLength(media.length); + }); + + it('can render a link to share on Diaspora', () => { + render( + corrupti} + media={['diaspora']} + /> + ); + + const link = rtlScreen.getByRole('link'); + + expect(link).toHaveTextContent('Share on Diaspora'); + expect(link).toHaveAttribute( + 'href', + `https://share.diasporafoundation.org/?title=${encodeURIComponent( + data.title + )}&url=${encodeURIComponent(data.url)}` + ); + }); + + it('can render a link to share on Facebook', () => { + render( + corrupti} + media={['facebook']} + /> + ); + + const link = rtlScreen.getByRole('link'); + + expect(link).toHaveTextContent('Share on Facebook'); + expect(link).toHaveAttribute( + 'href', + `https://www.facebook.com/sharer/sharer.php?$u=${encodeURIComponent( + data.url + )}` + ); + }); + + it('can render a link to share on Journal du Hacker', () => { + render( + corrupti} + media={['journal-du-hacker']} + /> + ); + + const link = rtlScreen.getByRole('link'); + + expect(link).toHaveTextContent('Share on Journal du Hacker'); + expect(link).toHaveAttribute( + 'href', + `https://www.journalduhacker.net/stories/new?title=${encodeURIComponent( + data.title + )}&url=${encodeURIComponent(data.url)}` + ); + }); + + it('can render a link to share on LinkedIn', () => { + render( + corrupti} + media={['linkedin']} + /> + ); + + const link = rtlScreen.getByRole('link'); + + expect(link).toHaveTextContent('Share on LinkedIn'); + expect(link).toHaveAttribute( + 'href', + `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent( + data.url + )}` + ); + }); + + it('can render a link to share on Twitter', () => { + render( + corrupti} + media={['twitter']} + /> + ); + + const link = rtlScreen.getByRole('link'); + + expect(link).toHaveTextContent('Share on Twitter'); + expect(link).toHaveAttribute( + 'href', + `https://twitter.com/intent/tweet?text=${encodeURIComponent( + data.title + )}&url=${encodeURIComponent(data.url)}` + ); + }); + + it('can render a link to share by Email', () => { + render( + corrupti} + media={['email']} + /> + ); + + const link = rtlScreen.getByRole('link'); + const subject = `You should read ${data.title}`; + const body = `${data.excerpt}\n\nRead more here: ${data.url}`; + + expect(link).toHaveTextContent('Share by Email'); + expect(link).toHaveAttribute( + 'href', + `mailto:?body=${encodeURIComponent(body)}&subject=${encodeURIComponent( + subject + )}` + ); + }); + + it('throws an error when a medium is invalid', () => { + expect(() => + render( + maxime} + // @ts-expect-error -- Unsupported medium + media={['not-supported']} + /> + ) + ).toThrowError('Unsupported social media.'); + }); +}); diff --git a/src/components/organisms/widgets/sharing-widget/sharing-widget.tsx b/src/components/organisms/widgets/sharing-widget/sharing-widget.tsx new file mode 100644 index 0000000..afac177 --- /dev/null +++ b/src/components/organisms/widgets/sharing-widget/sharing-widget.tsx @@ -0,0 +1,161 @@ +import { type ForwardRefRenderFunction, forwardRef, useCallback } from 'react'; +import { useIntl } from 'react-intl'; +import { + List, + ListItem, + SharingLink, + type SharingMedium, +} from '../../../atoms'; +import { Collapsible, type CollapsibleProps } from '../../../molecules'; + +export type SharingData = { + /** + * The content excerpt. + */ + excerpt: string; + /** + * The content title. + */ + title: string; + /** + * The content url. + */ + url: string; +}; + +const getUrl = ( + medium: Exclude, + data: Omit +) => { + const title = encodeURIComponent(data.title); + const url = encodeURIComponent(data.url); + + switch (medium) { + case 'diaspora': + return `https://share.diasporafoundation.org/?title=${title}&url=${url}`; + case 'facebook': + return `https://www.facebook.com/sharer/sharer.php?$u=${url}`; + case 'journal-du-hacker': + return `https://www.journalduhacker.net/stories/new?title=${title}&url=${url}`; + case 'linkedin': + return `https://www.linkedin.com/sharing/share-offsite/?url=${url}`; + case 'twitter': + return `https://twitter.com/intent/tweet?text=${title}&url=${url}`; + default: + throw new Error('Unsupported social media.'); + } +}; + +export type SharingWidgetProps = Omit< + CollapsibleProps, + 'children' | 'disablePadding' | 'hasBorders' +> & { + /** + * The page data to share. + */ + data: SharingData; + /** + * An ordered list of sharing medium to activate. + */ + media: SharingMedium[]; +}; + +const SharingWidgetWithRef: ForwardRefRenderFunction< + HTMLDivElement, + SharingWidgetProps +> = ({ data, media, ...props }, ref) => { + const intl = useIntl(); + const labels: Record = { + 'journal-du-hacker': intl.formatMessage({ + defaultMessage: 'Share on Journal du Hacker', + description: 'SharingWidget: Journal du Hacker sharing link', + id: 'Hclr0a', + }), + diaspora: intl.formatMessage({ + defaultMessage: 'Share on Diaspora', + description: 'SharingWidget: Diaspora sharing link', + id: '0f7fty', + }), + email: intl.formatMessage({ + defaultMessage: 'Share by Email', + description: 'SharingWidget: Email sharing link', + id: 'OWygWB', + }), + facebook: intl.formatMessage({ + defaultMessage: 'Share on Facebook', + description: 'SharingWidget: Facebook sharing link', + id: 'WzYUm5', + }), + linkedin: intl.formatMessage({ + defaultMessage: 'Share on LinkedIn', + description: 'SharingWidget: LinkedIn sharing link', + id: 'ofQPC+', + }), + twitter: intl.formatMessage({ + defaultMessage: 'Share on Twitter', + description: 'SharingWidget: Twitter sharing link', + id: 'QdBC6q', + }), + }; + + /** + * Build the mailto url from provided data. + * + * @returns {string} The mailto url with params. + */ + const buildEmailUrl = useCallback((): string => { + const readMore = intl.formatMessage({ + defaultMessage: 'Read more here:', + description: 'SharingWidget: content link prefix', + id: 'AsXE0d', + }); + const excerpt = data.excerpt + .replace(/<[^>]+>/gi, '') + .replaceAll(' ', ' '); + const body = `${excerpt}\n\n${readMore} ${data.url}`; + const subject = intl.formatMessage( + { + defaultMessage: 'You should read {title}', + description: 'SharingWidget: subject text', + id: 'BLq3+e', + }, + { title: data.title } + ); + + return `mailto:?body=${encodeURIComponent( + body + )}&subject=${encodeURIComponent(subject)}`; + }, [data, intl]); + + return ( + + + {media.map((medium) => ( + + + + ))} + + + ); +}; + +/** + * Sharing widget component + * + * Render a list of sharing links inside a widget. + */ +export const SharingWidget = forwardRef(SharingWidgetWithRef); diff --git a/src/components/organisms/widgets/sharing.module.scss b/src/components/organisms/widgets/sharing.module.scss deleted file mode 100644 index 24f6fc9..0000000 --- a/src/components/organisms/widgets/sharing.module.scss +++ /dev/null @@ -1,8 +0,0 @@ -.list { - display: flex; - flex-flow: row wrap; - gap: var(--spacing-xs); - margin: 0; - padding: 0 var(--spacing-2xs); - list-style-type: none; -} diff --git a/src/components/organisms/widgets/sharing.stories.tsx b/src/components/organisms/widgets/sharing.stories.tsx deleted file mode 100644 index d2be621..0000000 --- a/src/components/organisms/widgets/sharing.stories.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import type { ComponentMeta, ComponentStory } from '@storybook/react'; -import { Sharing as SharingWidget } from './sharing'; - -/** - * Sharing - Storybook Meta - */ -export default { - title: 'Organisms/Widgets', - component: SharingWidget, - argTypes: { - className: { - control: { - type: 'text', - }, - description: 'Set additional classnames to the sharing links list.', - table: { - category: 'Styles', - }, - type: { - name: 'string', - required: false, - }, - }, - data: { - description: 'The page data.', - type: { - name: 'object', - required: true, - value: {}, - }, - }, - media: { - control: { - type: null, - }, - description: 'An array of active and ordered sharing medium.', - type: { - name: 'string', - required: true, - }, - }, - }, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ( - -); - -/** - * Widgets Stories - Sharing - */ -export const Sharing = Template.bind({}); -Sharing.args = { - data: { - excerpt: - 'Alias similique eius ducimus laudantium aspernatur. Est rem ut eum temporibus sit reprehenderit aut non molestias. Vel dolorem expedita labore quo inventore aliquid nihil nam. Possimus nobis enim quas corporis eos.', - title: 'Accusantium totam nostrum', - url: 'https://www.example.test', - }, - media: ['diaspora', 'facebook', 'linkedin', 'twitter', 'email'], -}; diff --git a/src/components/organisms/widgets/sharing.test.tsx b/src/components/organisms/widgets/sharing.test.tsx deleted file mode 100644 index c7211f0..0000000 --- a/src/components/organisms/widgets/sharing.test.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { describe, expect, it } from '@jest/globals'; -import { render, screen as rtlScreen } from '../../../../tests/utils'; -import { Sharing, type SharingData } from './sharing'; - -const postData: SharingData = { - excerpt: 'A post excerpt', - title: 'A post title', - url: 'https://sharing-website.test', -}; - -describe('Sharing', () => { - it('renders a sharing widget', () => { - render(); - expect( - rtlScreen.getByRole('link', { name: 'Share on Facebook' }) - ).toBeInTheDocument(); - expect( - rtlScreen.getByRole('link', { name: 'Share on Twitter' }) - ).toBeInTheDocument(); - expect( - rtlScreen.queryByRole('link', { name: 'Share on LinkedIn' }) - ).not.toBeInTheDocument(); - }); -}); diff --git a/src/components/organisms/widgets/sharing.tsx b/src/components/organisms/widgets/sharing.tsx deleted file mode 100644 index 47ec49d..0000000 --- a/src/components/organisms/widgets/sharing.tsx +++ /dev/null @@ -1,259 +0,0 @@ -import type { FC } from 'react'; -import { useIntl } from 'react-intl'; -import { Heading, SharingLink, type SharingMedium } from '../../atoms'; -import { Collapsible, type CollapsibleProps } from '../../molecules'; -import styles from './sharing.module.scss'; - -/** - * Build the Diaspora sharing url with provided data. - * - * @param {string} title - The content title. - * @param {string} url - The content url. - * @returns {string} The Diaspora url. - */ -const buildDiasporaUrl = (title: string, url: string): string => { - const titleParam = `title=${encodeURI(title)}`; - const urlParam = `url=${encodeURI(url)}`; - return `https://share.diasporafoundation.org/?${titleParam}&${urlParam}`; -}; - -/** - * Build the Facebook sharing url with provided data. - * - * @param {string} url - The content url. - * @returns {string} The Facebook url. - */ -const buildFacebookUrl = (url: string): string => { - const urlParam = `u=${encodeURI(url)}`; - return `https://www.facebook.com/sharer/sharer.php?${urlParam}`; -}; - -/** - * Build the Journal du Hacker sharing url with provided data. - * - * @param {string} title - The content title. - * @param {string} url - The content url. - * @returns {string} The Journal du Hacker url. - */ -const buildJdHUrl = (title: string, url: string): string => { - const titleParam = `title=${encodeURI(title)}`; - const urlParam = `url=${encodeURI(url)}`; - return `https://www.journalduhacker.net/stories/new?${titleParam}&${urlParam}`; -}; - -/** - * Build the LinkedIn sharing url with provided data. - * - * @param {string} url - The content url. - * @returns {string} The LinkedIn url. - */ -const buildLinkedInUrl = (url: string): string => { - const urlParam = `url=${encodeURI(url)}`; - return `https://www.linkedin.com/sharing/share-offsite/?${urlParam}`; -}; - -/** - * Build the Twitter sharing url with provided data. - * - * @param {string} title - The content title. - * @param {string} url - The content url. - * @returns {string} The Twitter url. - */ -const buildTwitterUrl = (title: string, url: string): string => { - const titleParam = `text=${encodeURI(title)}`; - const urlParam = `url=${encodeURI(url)}`; - return `https://twitter.com/intent/tweet?${titleParam}&${urlParam}`; -}; - -export type SharingData = { - /** - * The content excerpt. - */ - excerpt: string; - /** - * The content title. - */ - title: string; - /** - * The content url. - */ - url: string; -}; - -export type SharingProps = Omit & { - /** - * Set additional classnames to the sharing links list. - */ - className?: string; - /** - * The page data to share. - */ - data: SharingData; - /** - * A list of active and ordered sharing medium. - */ - media: SharingMedium[]; -}; - -/** - * Sharing widget component - * - * Render a list of sharing links inside a widget. - */ -export const Sharing: FC = ({ - className = '', - data, - media, - ...props -}) => { - const listClass = `${styles.list} ${className}`; - const intl = useIntl(); - const widgetTitle = intl.formatMessage({ - defaultMessage: 'Share', - id: 'q3U6uI', - description: 'Sharing: widget title', - }); - - /** - * Build the mailto url from provided data. - * - * @param {string} excerpt - The content excerpt. - * @param {string} title - The content title. - * @param {string} url - The content url. - * @returns {string} The mailto url with params. - */ - const buildEmailUrl = ( - excerpt: string, - title: string, - url: string - ): string => { - const intro = intl.formatMessage({ - defaultMessage: 'Introduction:', - description: 'Sharing: email content prefix', - id: 'yfgMcl', - }); - const readMore = intl.formatMessage({ - defaultMessage: 'Read more here:', - description: 'Sharing: content link prefix', - id: 'UsQske', - }); - const body = `${intro}\n\n"${excerpt}"\n\n${readMore} ${url}`; - const bodyParam = excerpt ? `body=${encodeURI(body)}` : ''; - - const subject = intl.formatMessage( - { - defaultMessage: 'You should read {title}', - description: 'Sharing: subject text', - id: 'azgQuH', - }, - { title } - ); - const subjectParam = `subject=${encodeURI(subject)}`; - - return `mailto:?${bodyParam}&${subjectParam}`; - }; - - /** - * Retrieve the sharing label by medium id. - * - * @param {SharingMedium} medium - A sharing medium id. - * @returns {string} The sharing label. - */ - const getLabel = (medium: SharingMedium): string => { - switch (medium) { - case 'diaspora': - return intl.formatMessage({ - defaultMessage: 'Share on Diaspora', - description: 'Sharing: Diaspora sharing link', - id: 'oVLRW8', - }); - case 'email': - return intl.formatMessage({ - defaultMessage: 'Share by Email', - description: 'Sharing: Email sharing link', - id: '2ukj9H', - }); - case 'facebook': - return intl.formatMessage({ - defaultMessage: 'Share on Facebook', - description: 'Sharing: Facebook sharing link', - id: 'o0DAK4', - }); - case 'journal-du-hacker': - return intl.formatMessage({ - defaultMessage: 'Share on Journal du Hacker', - description: 'Sharing: Journal du Hacker sharing link', - id: 'vnbryZ', - }); - case 'linkedin': - return intl.formatMessage({ - defaultMessage: 'Share on LinkedIn', - description: 'Sharing: LinkedIn sharing link', - id: 'Y+DYja', - }); - case 'twitter': - default: - return intl.formatMessage({ - defaultMessage: 'Share on Twitter', - description: 'Sharing: Twitter sharing link', - id: 'NI5gXc', - }); - } - }; - - /** - * Retrieve the sharing url by medium id. - * - * @param {SharingMedium} medium - A sharing medium id. - * @returns {string} The sharing url. - */ - const getUrl = (medium: SharingMedium): string => { - const { excerpt, title, url } = data; - - switch (medium) { - case 'diaspora': - return buildDiasporaUrl(title, url); - case 'email': - return buildEmailUrl(excerpt, title, url); - case 'facebook': - return buildFacebookUrl(url); - case 'journal-du-hacker': - return buildJdHUrl(title, url); - case 'linkedin': - return buildLinkedInUrl(url); - case 'twitter': - return buildTwitterUrl(title, url); - default: - return '#'; - } - }; - - /** - * Get the sharing list items. - * - * @returns {JSX.Element[]} The sharing links wrapped with li element. - */ - const getItems = (): JSX.Element[] => - media.map((medium) => ( -
  • - -
  • - )); - - return ( - - {widgetTitle} - - } - > -
      {getItems()}
    -
    - ); -}; diff --git a/src/components/templates/page/page-layout.stories.tsx b/src/components/templates/page/page-layout.stories.tsx index 20740db..9f0cce1 100644 --- a/src/components/templates/page/page-layout.stories.tsx +++ b/src/components/templates/page/page-layout.stories.tsx @@ -1,6 +1,6 @@ import type { ComponentMeta, ComponentStory } from '@storybook/react'; import { ButtonLink, Heading, Link } from '../../atoms'; -import { LinksListWidget, PostsList, Sharing } from '../../organisms'; +import { LinksListWidget, PostsList, SharingWidget } from '../../organisms'; import { LayoutBase } from '../layout/layout.stories'; import { PageLayout as PageLayoutComponent } from './page-layout'; @@ -239,9 +239,10 @@ SinglePage.args = { ), widgets: [ - Share} media={[ 'diaspora', 'email', @@ -330,9 +331,10 @@ Post.args = { ), widgets: [ - Share} media={[ 'diaspora', 'email', diff --git a/src/i18n/en.json b/src/i18n/en.json index 2b18178..02fe61b 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -31,6 +31,10 @@ "defaultMessage": "Related thematics", "description": "TopicPage: related thematics list widget title" }, + "0f7fty": { + "defaultMessage": "Share on Diaspora", + "description": "SharingWidget: Diaspora sharing link" + }, "0gVlI3": { "defaultMessage": "Tracking:", "description": "AckeeToggle: select label" @@ -75,10 +79,6 @@ "defaultMessage": "Written by:", "description": "PostPreviewMeta: author label" }, - "2ukj9H": { - "defaultMessage": "Share by Email", - "description": "Sharing: Email sharing link" - }, "310o3F": { "defaultMessage": "Error 404: Page not found - {websiteName}", "description": "404Page: SEO - Page title" @@ -191,6 +191,10 @@ "defaultMessage": "Pagination", "description": "BlogPage: pagination accessible name" }, + "AsXE0d": { + "defaultMessage": "Read more here:", + "description": "SharingWidget: content link prefix" + }, "B1lS/v": { "defaultMessage": "Reading time:", "description": "PostPreviewMeta: reading time label" @@ -203,6 +207,10 @@ "defaultMessage": "Others formats", "description": "CVPage: cv preview widget title" }, + "BLq3+e": { + "defaultMessage": "You should read {title}", + "description": "SharingWidget: subject text" + }, "BYdQze": { "defaultMessage": "Read more about {postTitle}", "description": "PostPreview: read more link" @@ -267,6 +275,14 @@ "defaultMessage": "Reading time:", "description": "ArticlePage: reading time label" }, + "HKKkQk": { + "defaultMessage": "Share", + "description": "SharingWidget: widget title" + }, + "Hclr0a": { + "defaultMessage": "Share on Journal du Hacker", + "description": "SharingWidget: Journal du Hacker sharing link" + }, "HohQPh": { "defaultMessage": "Thematics", "description": "Error404Page: thematics list widget title" @@ -343,10 +359,6 @@ "defaultMessage": "Topics", "description": "SearchPage: topics list widget title" }, - "NI5gXc": { - "defaultMessage": "Share on Twitter", - "description": "Sharing: Twitter sharing link" - }, "NfAn9N": { "defaultMessage": "{commentsCount, plural, =0 {No comments} one {# comment} other {# comments}} about {title}", "description": "PostPreviewMeta: comments count" @@ -367,6 +379,10 @@ "defaultMessage": "Technologies:", "description": "ProjectOverview: technologies label" }, + "OWygWB": { + "defaultMessage": "Share by Email", + "description": "SharingWidget: Email sharing link" + }, "OevMeU": { "defaultMessage": "{minutesCount} minutes {secondsCount} seconds", "description": "useReadingTime: minutes + seconds count" @@ -395,6 +411,10 @@ "defaultMessage": "Reply", "description": "CommentsList: reply button" }, + "QdBC6q": { + "defaultMessage": "Share on Twitter", + "description": "SharingWidget: Twitter sharing link" + }, "Qh2CwH": { "defaultMessage": "Find me elsewhere", "description": "ContactPage: social media widget title" @@ -435,10 +455,6 @@ "defaultMessage": "Published on:", "description": "ThematicPage: publication date label" }, - "UsQske": { - "defaultMessage": "Read more here:", - "description": "Sharing: content link prefix" - }, "VkAnvv": { "defaultMessage": "Send", "description": "ContactForm: send button" @@ -463,6 +479,10 @@ "defaultMessage": "Search", "description": "SearchForm: button accessible name" }, + "WzYUm5": { + "defaultMessage": "Share on Facebook", + "description": "SharingWidget: Facebook sharing link" + }, "X8oujO": { "defaultMessage": "Search for:", "description": "SearchForm: field accessible label" @@ -475,10 +495,6 @@ "defaultMessage": "Open search", "description": "Layout: search button label in navbar" }, - "Y+DYja": { - "defaultMessage": "Share on LinkedIn", - "description": "Sharing: LinkedIn sharing link" - }, "YV//MH": { "defaultMessage": "No results found.", "description": "SearchPage: no results" @@ -511,10 +527,6 @@ "defaultMessage": "{topicsCount, plural, =0 {Topics:} one {Topic:} other {Topics:}}", "description": "PostPreviewMeta: topics label" }, - "azgQuH": { - "defaultMessage": "You should read {title}", - "description": "Sharing: subject text" - }, "bPv0VG": { "defaultMessage": "Contact form", "description": "Contact: form accessible name" @@ -651,17 +663,13 @@ "defaultMessage": "Legal notice", "description": "Layout: Legal notice label" }, - "o0DAK4": { - "defaultMessage": "Share on Facebook", - "description": "Sharing: Facebook sharing link" - }, "o3WSz5": { "defaultMessage": "Settings", "description": "Layout: settings modal title in navbar" }, - "oVLRW8": { - "defaultMessage": "Share on Diaspora", - "description": "Sharing: Diaspora sharing link" + "ofQPC+": { + "defaultMessage": "Share on LinkedIn", + "description": "SharingWidget: LinkedIn sharing link" }, "og/zWL": { "defaultMessage": "Dark theme", @@ -683,10 +691,6 @@ "defaultMessage": "Discover search results for {query} on {websiteName}.", "description": "SearchPage: SEO - Meta description" }, - "q3U6uI": { - "defaultMessage": "Share", - "description": "Sharing: widget title" - }, "qnwsWV": { "defaultMessage": "Projects", "description": "Layout: main nav - projects link" @@ -751,10 +755,6 @@ "defaultMessage": "Web development", "description": "HomePage: link to web development thematic" }, - "vnbryZ": { - "defaultMessage": "Share on Journal du Hacker", - "description": "Sharing: Journal du Hacker sharing link" - }, "vtDLzG": { "defaultMessage": "Would you like to try a new search?", "description": "SearchPage: try a new search message" @@ -787,10 +787,6 @@ "defaultMessage": "Message:", "description": "ContactForm: message label" }, - "yfgMcl": { - "defaultMessage": "Introduction:", - "description": "Sharing: email content prefix" - }, "zEN3fd": { "defaultMessage": "All posts in {topicName}", "description": "TopicPage: posts list heading" diff --git a/src/i18n/fr.json b/src/i18n/fr.json index 1dd1688..27eb582 100644 --- a/src/i18n/fr.json +++ b/src/i18n/fr.json @@ -31,6 +31,10 @@ "defaultMessage": "Thématiques liées", "description": "TopicPage: related thematics list widget title" }, + "0f7fty": { + "defaultMessage": "Partager sur Diaspora", + "description": "SharingWidget: Diaspora sharing link" + }, "0gVlI3": { "defaultMessage": "Suivi :", "description": "AckeeToggle: select label" @@ -75,10 +79,6 @@ "defaultMessage": "Écrit par :", "description": "PostPreviewMeta: author label" }, - "2ukj9H": { - "defaultMessage": "Partager par email", - "description": "Sharing: Email sharing link" - }, "310o3F": { "defaultMessage": "Erreur 404 : Page non trouvée - {websiteName}", "description": "404Page: SEO - Page title" @@ -191,6 +191,10 @@ "defaultMessage": "Pagination", "description": "BlogPage: pagination accessible name" }, + "AsXE0d": { + "defaultMessage": "En lire plus ici :", + "description": "SharingWidget: content link prefix" + }, "B1lS/v": { "defaultMessage": "Temps de lecture :", "description": "PostPreviewMeta: reading time label" @@ -203,6 +207,10 @@ "defaultMessage": "Autres formats", "description": "CVPage: cv preview widget title" }, + "BLq3+e": { + "defaultMessage": "Vous devriez lire {title}", + "description": "SharingWidget: subject text" + }, "BYdQze": { "defaultMessage": "En lire plus à propos de {postTitle}", "description": "PostPreview: read more link" @@ -267,6 +275,14 @@ "defaultMessage": "Temps de lecture :", "description": "ArticlePage: reading time label" }, + "HKKkQk": { + "defaultMessage": "Partager", + "description": "SharingWidget: widget title" + }, + "Hclr0a": { + "defaultMessage": "Partager sur le Journal du Hacker", + "description": "SharingWidget: Journal du Hacker sharing link" + }, "HohQPh": { "defaultMessage": "Thématiques", "description": "Error404Page: thematics list widget title" @@ -343,10 +359,6 @@ "defaultMessage": "Sujets", "description": "SearchPage: topics list widget title" }, - "NI5gXc": { - "defaultMessage": "Partager sur Twitter", - "description": "Sharing: Twitter sharing link" - }, "NfAn9N": { "defaultMessage": "{commentsCount, plural, =0 {0 commentaire} one {# commentaire} other {# commentaires}} à propos de {title}", "description": "PostPreviewMeta: comments count" @@ -367,6 +379,10 @@ "defaultMessage": "Technologies :", "description": "ProjectOverview: technologies label" }, + "OWygWB": { + "defaultMessage": "Partager par email", + "description": "SharingWidget: Email sharing link" + }, "OevMeU": { "defaultMessage": "{minutesCount} minutes {secondsCount} secondes", "description": "useReadingTime: minutes + seconds count" @@ -395,6 +411,10 @@ "defaultMessage": "Répondre", "description": "CommentsList: reply button" }, + "QdBC6q": { + "defaultMessage": "Partager sur Twitter", + "description": "SharingWidget: Twitter sharing link" + }, "Qh2CwH": { "defaultMessage": "Retrouvez-moi ailleurs", "description": "ContactPage: social media widget title" @@ -435,10 +455,6 @@ "defaultMessage": "Publié le :", "description": "ThematicPage: publication date label" }, - "UsQske": { - "defaultMessage": "En lire plus ici :", - "description": "Sharing: content link prefix" - }, "VkAnvv": { "defaultMessage": "Envoyer", "description": "ContactForm: send button" @@ -463,6 +479,10 @@ "defaultMessage": "Rechercher", "description": "SearchForm: button accessible name" }, + "WzYUm5": { + "defaultMessage": "Partager sur Facebook", + "description": "SharingWidget: Facebook sharing link" + }, "X8oujO": { "defaultMessage": "Rechercher :", "description": "SearchForm: field accessible label" @@ -475,10 +495,6 @@ "defaultMessage": "Ouvrir la recherche", "description": "Layout: search button label in navbar" }, - "Y+DYja": { - "defaultMessage": "Partager sur LinkedIn", - "description": "Sharing: LinkedIn sharing link" - }, "YV//MH": { "defaultMessage": "Aucun résultat.", "description": "SearchPage: no results" @@ -511,10 +527,6 @@ "defaultMessage": "{topicsCount, plural, =0 {Sujets :} one {Sujet :} other {Sujets :}}", "description": "PostPreviewMeta: topics label" }, - "azgQuH": { - "defaultMessage": "Vous devriez lire {title}", - "description": "Sharing: subject text" - }, "bPv0VG": { "defaultMessage": "Formulaire de contact", "description": "Contact: form accessible name" @@ -651,17 +663,13 @@ "defaultMessage": "Mentions légales", "description": "Layout: Legal notice label" }, - "o0DAK4": { - "defaultMessage": "Partager sur Facebook", - "description": "Sharing: Facebook sharing link" - }, "o3WSz5": { "defaultMessage": "Réglages", "description": "Layout: settings modal title in navbar" }, - "oVLRW8": { - "defaultMessage": "Partager sur Diaspora", - "description": "Sharing: Diaspora sharing link" + "ofQPC+": { + "defaultMessage": "Partager sur LinkedIn", + "description": "SharingWidget: LinkedIn sharing link" }, "og/zWL": { "defaultMessage": "Thème sombre", @@ -683,10 +691,6 @@ "defaultMessage": "Découvrez les résultats de recherche pour {query} sur {websiteName}.", "description": "SearchPage: SEO - Meta description" }, - "q3U6uI": { - "defaultMessage": "Partager", - "description": "Sharing: widget title" - }, "qnwsWV": { "defaultMessage": "Projets", "description": "Layout: main nav - projects link" @@ -751,10 +755,6 @@ "defaultMessage": "Développement web", "description": "HomePage: link to web development thematic" }, - "vnbryZ": { - "defaultMessage": "Partager sur le Journal du Hacker", - "description": "Sharing: Journal du Hacker sharing link" - }, "vtDLzG": { "defaultMessage": "Souhaitez-vous essayer une nouvelle recherche ?", "description": "SearchPage: try a new search message" @@ -787,10 +787,6 @@ "defaultMessage": "Message :", "description": "ContactForm: message label" }, - "yfgMcl": { - "defaultMessage": "Introduction :", - "description": "Sharing: email content prefix" - }, "zEN3fd": { "defaultMessage": "Tous les articles dans {topicName}", "description": "TopicPage: posts list heading" diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx index d35541a..4eb7f2b 100644 --- a/src/pages/article/[slug].tsx +++ b/src/pages/article/[slug].tsx @@ -13,11 +13,12 @@ import { getLayout, Link, PageLayout, - Sharing, + SharingWidget, Spinner, type MetaItemData, Time, type CommentData, + Heading, } from '../../components'; import { getAllArticlesSlugs, @@ -301,6 +302,11 @@ const ArticlePage: NextPageWithLayout = ({ ); const pageUrl = `${website.url}${slug}`; + const sharingWidgetTitle = intl.formatMessage({ + defaultMessage: 'Share', + id: 'HKKkQk', + description: 'SharingWidget: widget title', + }); return ( <> @@ -335,11 +341,12 @@ const ArticlePage: NextPageWithLayout = ({ title={title} withToC={true} widgets={[ - {sharingWidgetTitle}} media={[ 'diaspora', 'email', diff --git a/src/pages/projets/[slug].tsx b/src/pages/projets/[slug].tsx index 58c03ce..fa8f43a 100644 --- a/src/pages/projets/[slug].tsx +++ b/src/pages/projets/[slug].tsx @@ -13,7 +13,7 @@ import { getLayout, Link, PageLayout, - Sharing, + SharingWidget, Spinner, Heading, List, @@ -289,6 +289,11 @@ const ProjectPage: NextPageWithLayout = ({ project }) => { title, }); const schemaJsonLd = getSchemaJson([webpageSchema, articleSchema]); + const sharingWidgetTitle = intl.formatMessage({ + defaultMessage: 'Share', + id: 'HKKkQk', + description: 'SharingWidget: widget title', + }); return ( <> @@ -317,10 +322,11 @@ const ProjectPage: NextPageWithLayout = ({ project }) => { headerMeta={filteredHeaderMeta} withToC={true} widgets={[ - {sharingWidgetTitle}} media={[ 'diaspora', 'email', diff --git a/src/styles/pages/article.module.scss b/src/styles/pages/article.module.scss index 5e7d520..7aac5a7 100644 --- a/src/styles/pages/article.module.scss +++ b/src/styles/pages/article.module.scss @@ -66,8 +66,9 @@ .widget { @include mix.media("screen") { @include mix.dimensions("md") { - width: min-content; - gap: var(--spacing-2xs); + ul { + width: min-content; + } } } } -- cgit v1.2.3