aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-11-13 19:03:44 +0100
committerArmand Philippot <git@armandphilippot.com>2023-11-13 19:03:44 +0100
commitfb29b0f017fae162ffa7ad6bdfc80099346802de (patch)
tree3f8aebb73457ee27b86b8b1a3106a5f9bc35e8da /src
parente331106e56d59a8b987230860b66214139c12ef6 (diff)
refactor(components): replace SocialMedia with SocialMediaWidget
* the goal is to make the name of the widgets coherent * remove useless CSS * replace Media type with SocialMediaData
Diffstat (limited to 'src')
-rw-r--r--src/components/organisms/widgets/index.ts2
-rw-r--r--src/components/organisms/widgets/social-media-widget/index.ts1
-rw-r--r--src/components/organisms/widgets/social-media-widget/social-media-widget.stories.tsx (renamed from src/components/organisms/widgets/social-media.stories.tsx)10
-rw-r--r--src/components/organisms/widgets/social-media-widget/social-media-widget.test.tsx27
-rw-r--r--src/components/organisms/widgets/social-media-widget/social-media-widget.tsx43
-rw-r--r--src/components/organisms/widgets/social-media.module.scss5
-rw-r--r--src/components/organisms/widgets/social-media.test.tsx47
-rw-r--r--src/components/organisms/widgets/social-media.tsx40
-rw-r--r--src/pages/contact.tsx4
-rw-r--r--src/pages/cv.tsx4
10 files changed, 81 insertions, 102 deletions
diff --git a/src/components/organisms/widgets/index.ts b/src/components/organisms/widgets/index.ts
index 222ade0..03f845f 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 './social-media';
+export * from './social-media-widget';
export * from './table-of-contents';
diff --git a/src/components/organisms/widgets/social-media-widget/index.ts b/src/components/organisms/widgets/social-media-widget/index.ts
new file mode 100644
index 0000000..33a6f3f
--- /dev/null
+++ b/src/components/organisms/widgets/social-media-widget/index.ts
@@ -0,0 +1 @@
+export * from './social-media-widget';
diff --git a/src/components/organisms/widgets/social-media.stories.tsx b/src/components/organisms/widgets/social-media-widget/social-media-widget.stories.tsx
index 8064157..5c6efb0 100644
--- a/src/components/organisms/widgets/social-media.stories.tsx
+++ b/src/components/organisms/widgets/social-media-widget/social-media-widget.stories.tsx
@@ -1,16 +1,16 @@
import type { ComponentMeta, ComponentStory } from '@storybook/react';
-import { Heading } from '../../atoms';
-import { SocialMedia as SocialMediaWidget, type Media } from './social-media';
+import { Heading } from '../../../atoms';
+import { SocialMediaWidget, type SocialMediaData } from './social-media-widget';
/**
* SocialMedia - Storybook Meta
*/
export default {
- title: 'Organisms/Widgets',
+ title: 'Organisms/Widgets/SocialMedia',
component: SocialMediaWidget,
argTypes: {
media: {
- description: 'The links data.',
+ description: 'The social media data.',
type: {
name: 'object',
required: true,
@@ -24,7 +24,7 @@ const Template: ComponentStory<typeof SocialMediaWidget> = (args) => (
<SocialMediaWidget {...args} />
);
-const media: Media[] = [
+const media: SocialMediaData[] = [
{ icon: 'Github', id: 'github', label: 'Github', url: '#' },
{ icon: 'LinkedIn', id: 'gitlab', label: 'Gitlab', url: '#' },
];
diff --git a/src/components/organisms/widgets/social-media-widget/social-media-widget.test.tsx b/src/components/organisms/widgets/social-media-widget/social-media-widget.test.tsx
new file mode 100644
index 0000000..197b9ac
--- /dev/null
+++ b/src/components/organisms/widgets/social-media-widget/social-media-widget.test.tsx
@@ -0,0 +1,27 @@
+import { describe, expect, it } from '@jest/globals';
+import { render, screen as rtlScreen } from '@testing-library/react';
+import { Heading } from '../../../atoms';
+import { type SocialMediaData, SocialMediaWidget } from './social-media-widget';
+
+describe('SocialMediaWidget', () => {
+ it('render the widget heading and a list of social media', () => {
+ const heading = 'aut dolorem molestiae';
+ const headingLvl = 3;
+ const media = [
+ { icon: 'Github', id: 'github', label: 'Github', url: '#github' },
+ { icon: 'LinkedIn', id: 'linkedin', label: 'LinkedIn', url: '#linkedin' },
+ ] satisfies SocialMediaData[];
+
+ render(
+ <SocialMediaWidget
+ heading={<Heading level={headingLvl}>{heading}</Heading>}
+ media={media}
+ />
+ );
+
+ expect(
+ rtlScreen.getByRole('heading', { level: headingLvl })
+ ).toHaveTextContent(heading);
+ expect(rtlScreen.getAllByRole('link')).toHaveLength(media.length);
+ });
+});
diff --git a/src/components/organisms/widgets/social-media-widget/social-media-widget.tsx b/src/components/organisms/widgets/social-media-widget/social-media-widget.tsx
new file mode 100644
index 0000000..d75f48f
--- /dev/null
+++ b/src/components/organisms/widgets/social-media-widget/social-media-widget.tsx
@@ -0,0 +1,43 @@
+import { forwardRef, type ForwardRefRenderFunction } from 'react';
+import {
+ List,
+ ListItem,
+ SocialLink,
+ type SocialLinkProps,
+} from '../../../atoms';
+import { Collapsible, type CollapsibleProps } from '../../../molecules';
+
+export type SocialMediaData = Required<
+ Pick<SocialLinkProps, 'icon' | 'id' | 'label' | 'url'>
+>;
+
+export type SocialMediaProps = Omit<CollapsibleProps, 'children'> & {
+ media: SocialMediaData[];
+};
+
+const SocialMediaWidgetWithRef: ForwardRefRenderFunction<
+ HTMLDivElement,
+ SocialMediaProps
+> = ({ media, ...props }, ref) => (
+ <Collapsible {...props} ref={ref}>
+ <List
+ hideMarker
+ isInline
+ // eslint-disable-next-line react/jsx-no-literals
+ spacing="xs"
+ >
+ {media.map(({ id, ...link }) => (
+ <ListItem key={id}>
+ <SocialLink {...link} />
+ </ListItem>
+ ))}
+ </List>
+ </Collapsible>
+);
+
+/**
+ * Social Media widget component
+ *
+ * Render a social media list with links.
+ */
+export const SocialMediaWidget = forwardRef(SocialMediaWidgetWithRef);
diff --git a/src/components/organisms/widgets/social-media.module.scss b/src/components/organisms/widgets/social-media.module.scss
deleted file mode 100644
index 1cd3f57..0000000
--- a/src/components/organisms/widgets/social-media.module.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-@use "../../../styles/abstracts/placeholders";
-
-.list {
- padding: 0 var(--spacing-2xs);
-}
diff --git a/src/components/organisms/widgets/social-media.test.tsx b/src/components/organisms/widgets/social-media.test.tsx
deleted file mode 100644
index ead29d9..0000000
--- a/src/components/organisms/widgets/social-media.test.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import { describe, expect, it } from '@jest/globals';
-import { render, screen as rtlScreen } from '../../../../tests/utils';
-import { SocialMedia, type Media } from './social-media';
-import { Heading } from 'src/components/atoms';
-
-const media: Media[] = [
- { icon: 'Github', id: 'github', label: 'Github', url: '#' },
- { icon: 'LinkedIn', id: 'gitlab', label: 'Gitlab', url: '#' },
-];
-const title = 'Dolores ut ut';
-const titleLevel = 2;
-
-/**
- * Next.js mock images with next/image component. So for now, I need to mock
- * the svg files manually.
- */
-jest.mock('@assets/images/social-media/github.svg', () => 'svg-file');
-jest.mock('@assets/images/social-media/gitlab.svg', () => 'svg-file');
-jest.mock('@assets/images/social-media/linkedin.svg', () => 'svg-file');
-jest.mock('@assets/images/social-media/twitter.svg', () => 'svg-file');
-
-describe('SocialMedia', () => {
- it('renders the widget title', () => {
- render(
- <SocialMedia
- heading={<Heading level={titleLevel}>{title}</Heading>}
- media={media}
- />
- );
- expect(
- rtlScreen.getByRole('heading', {
- level: titleLevel,
- name: new RegExp(title, 'i'),
- })
- ).toBeInTheDocument();
- });
-
- it('renders the correct number of items', () => {
- render(
- <SocialMedia
- heading={<Heading level={titleLevel}>{title}</Heading>}
- media={media}
- />
- );
- expect(rtlScreen.getAllByRole('listitem')).toHaveLength(media.length);
- });
-});
diff --git a/src/components/organisms/widgets/social-media.tsx b/src/components/organisms/widgets/social-media.tsx
deleted file mode 100644
index 14c8fe6..0000000
--- a/src/components/organisms/widgets/social-media.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import type { FC } from 'react';
-import { List, ListItem, SocialLink, type SocialLinkProps } from '../../atoms';
-import { Collapsible, type CollapsibleProps } from '../../molecules';
-import styles from './social-media.module.scss';
-
-export type Media = Required<
- Pick<SocialLinkProps, 'icon' | 'id' | 'label' | 'url'>
->;
-
-export type SocialMediaProps = Omit<CollapsibleProps, 'children'> & {
- media: Media[];
-};
-
-/**
- * Social Media widget component
- *
- * Render a social media list with links.
- */
-export const SocialMedia: FC<SocialMediaProps> = ({ media, ...props }) => {
- /**
- * Retrieve the social media items.
- *
- * @param {SocialMedia[]} links - An array of social media name and url.
- * @returns {JSX.Element[]} The social links.
- */
- const getItems = (links: Media[]): JSX.Element[] =>
- links.map(({ id, ...link }) => (
- <ListItem key={id}>
- <SocialLink {...link} />
- </ListItem>
- ));
-
- return (
- <Collapsible {...props}>
- <List className={styles.list} hideMarker isInline spacing="xs">
- {getItems(media)}
- </List>
- </Collapsible>
- );
-};
diff --git a/src/pages/contact.tsx b/src/pages/contact.tsx
index 094d15a..916e04c 100644
--- a/src/pages/contact.tsx
+++ b/src/pages/contact.tsx
@@ -9,7 +9,7 @@ import {
ContactForm,
getLayout,
PageLayout,
- SocialMedia,
+ SocialMediaWidget,
Heading,
type ContactFormSubmit,
} from '../components';
@@ -80,7 +80,7 @@ const ContactPage: NextPageWithLayout = () => {
});
const widgets = [
- <SocialMedia
+ <SocialMediaWidget
heading={
<Heading isFake level={3}>
{socialMediaTitle}
diff --git a/src/pages/cv.tsx b/src/pages/cv.tsx
index ad643c3..e2d1ae5 100644
--- a/src/pages/cv.tsx
+++ b/src/pages/cv.tsx
@@ -18,7 +18,7 @@ import {
Link,
List,
PageLayout,
- SocialMedia,
+ SocialMediaWidget,
ListItem,
type MetaItemData,
Time,
@@ -223,7 +223,7 @@ const CVPage: NextPageWithLayout = () => {
// eslint-disable-next-line react/jsx-no-literals -- Key allowed
key="image-widget"
/>,
- <SocialMedia
+ <SocialMediaWidget
heading={
<Heading isFake level={3}>
{socialMediaTitle}