aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/organisms/widgets
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-09-29 21:29:45 +0200
committerArmand Philippot <git@armandphilippot.com>2023-11-11 18:14:41 +0100
commit4f768afe543bbf9e1857c41d03804f8e37ab3512 (patch)
treed751219a147688b5665c51db3c8dbdca1f1345ee /src/components/organisms/widgets
parent9128c224c65f8f2a172b22a443ccb4573c7acd90 (diff)
refactor(components): rewrite List component
* change `items` prop to children * replace `kind` prop with `isHierarchical`, `isOrdered` & `isInline` props * add `hideMarker` prop * add `spacing` prop to control item spacing * move lists styles to Sass placeholders to avoid repeats because of headless WordPress
Diffstat (limited to 'src/components/organisms/widgets')
-rw-r--r--src/components/organisms/widgets/links-list-widget.module.scss8
-rw-r--r--src/components/organisms/widgets/links-list-widget.stories.tsx22
-rw-r--r--src/components/organisms/widgets/links-list-widget.test.tsx13
-rw-r--r--src/components/organisms/widgets/links-list-widget.tsx67
-rw-r--r--src/components/organisms/widgets/social-media.module.scss5
-rw-r--r--src/components/organisms/widgets/social-media.tsx17
-rw-r--r--src/components/organisms/widgets/table-of-contents.stories.tsx7
-rw-r--r--src/components/organisms/widgets/table-of-contents.tsx9
8 files changed, 67 insertions, 81 deletions
diff --git a/src/components/organisms/widgets/links-list-widget.module.scss b/src/components/organisms/widgets/links-list-widget.module.scss
index 26f1549..4efc2d4 100644
--- a/src/components/organisms/widgets/links-list-widget.module.scss
+++ b/src/components/organisms/widgets/links-list-widget.module.scss
@@ -4,6 +4,8 @@
.widget {
.list {
.list {
+ padding: 0;
+
> *:first-child {
border-top: fun.convert-px(1) solid var(--color-primary);
}
@@ -35,8 +37,6 @@
}
&--ordered {
- @extend %reset-ordered-list;
-
counter-reset: link;
.list__link {
@@ -50,10 +50,6 @@
}
}
- &--unordered {
- @extend %reset-list;
- }
-
&__item {
&:not(:last-child) {
border-bottom: fun.convert-px(1) solid var(--color-primary);
diff --git a/src/components/organisms/widgets/links-list-widget.stories.tsx b/src/components/organisms/widgets/links-list-widget.stories.tsx
index 3f62502..2180de4 100644
--- a/src/components/organisms/widgets/links-list-widget.stories.tsx
+++ b/src/components/organisms/widgets/links-list-widget.stories.tsx
@@ -1,4 +1,4 @@
-import { ComponentMeta, ComponentStory } from '@storybook/react';
+import type { ComponentMeta, ComponentStory } from '@storybook/react';
import { LinksListWidget } from './links-list-widget';
/**
@@ -8,7 +8,7 @@ export default {
title: 'Organisms/Widgets/LinksList',
component: LinksListWidget,
args: {
- kind: 'unordered',
+ isOrdered: false,
},
argTypes: {
className: {
@@ -32,21 +32,6 @@ export default {
value: {},
},
},
- kind: {
- control: {
- type: 'select',
- },
- description: 'The list kind: either ordered or unordered.',
- options: ['ordered', 'unordered'],
- table: {
- category: 'Options',
- defaultValue: { summary: 'unordered' },
- },
- type: {
- name: 'string',
- required: false,
- },
- },
level: {
control: {
type: 'number',
@@ -105,7 +90,6 @@ const items = [
export const Unordered = Template.bind({});
Unordered.args = {
items,
- kind: 'unordered',
level: 2,
title: 'A list of links',
};
@@ -115,8 +99,8 @@ Unordered.args = {
*/
export const Ordered = Template.bind({});
Ordered.args = {
+ isOrdered: true,
items,
- kind: 'ordered',
level: 2,
title: 'A list of links',
};
diff --git a/src/components/organisms/widgets/links-list-widget.test.tsx b/src/components/organisms/widgets/links-list-widget.test.tsx
index 2d36eb5..6323e19 100644
--- a/src/components/organisms/widgets/links-list-widget.test.tsx
+++ b/src/components/organisms/widgets/links-list-widget.test.tsx
@@ -1,5 +1,5 @@
import { describe, expect, it } from '@jest/globals';
-import { render, screen } from '../../../../tests/utils';
+import { render, screen as rtlScreen } from '../../../../tests/utils';
import { LinksListWidget } from './links-list-widget';
const title = 'Voluptatem minus autem';
@@ -14,20 +14,19 @@ describe('LinksListWidget', () => {
it('renders a widget title', () => {
render(<LinksListWidget items={items} title={title} level={2} />);
expect(
- screen.getByRole('heading', { level: 2, name: new RegExp(title, 'i') })
+ rtlScreen.getByRole('heading', { level: 2, name: new RegExp(title, 'i') })
).toBeInTheDocument();
});
it('renders the correct number of items', () => {
render(<LinksListWidget items={items} title={title} level={2} />);
- expect(screen.getAllByRole('listitem')).toHaveLength(items.length);
+ expect(rtlScreen.getAllByRole('listitem')).toHaveLength(items.length);
});
it('renders some links', () => {
render(<LinksListWidget items={items} title={title} level={2} />);
- expect(screen.getByRole('link', { name: items[0].name })).toHaveAttribute(
- 'href',
- items[0].url
- );
+ expect(
+ rtlScreen.getByRole('link', { name: items[0].name })
+ ).toHaveAttribute('href', items[0].url);
});
});
diff --git a/src/components/organisms/widgets/links-list-widget.tsx b/src/components/organisms/widgets/links-list-widget.tsx
index df8430d..8f71efd 100644
--- a/src/components/organisms/widgets/links-list-widget.tsx
+++ b/src/components/organisms/widgets/links-list-widget.tsx
@@ -1,6 +1,6 @@
-import { FC } from 'react';
+import type { FC } from 'react';
import { slugify } from '../../../utils/helpers';
-import { Link, List, type ListItem, type ListProps } from '../../atoms';
+import { Link, List, ListItem } from '../../atoms';
import { Widget, type WidgetProps } from '../../molecules';
import styles from './links-list-widget.module.scss';
@@ -19,13 +19,19 @@ export type LinksListItems = {
url: string;
};
-export type LinksListWidgetProps = Pick<WidgetProps, 'level' | 'title'> &
- Pick<ListProps, 'className' | 'kind'> & {
- /**
- * An array of name/url couple.
- */
- items: LinksListItems[];
- };
+export type LinksListWidgetProps = Pick<WidgetProps, 'level' | 'title'> & {
+ className?: string;
+ /**
+ * Should the links be ordered?
+ *
+ * @default false
+ */
+ isOrdered?: boolean;
+ /**
+ * An array of name/url couple.
+ */
+ items: LinksListItems[];
+};
/**
* LinksListWidget component
@@ -34,11 +40,11 @@ export type LinksListWidgetProps = Pick<WidgetProps, 'level' | 'title'> &
*/
export const LinksListWidget: FC<LinksListWidgetProps> = ({
className = '',
+ isOrdered = false,
items,
- kind = 'unordered',
...props
}) => {
- const listKindClass = `list--${kind}`;
+ const listKindClass = `list--${isOrdered ? 'ordered' : 'unordered'}`;
/**
* Format the widget data to be used as List items.
@@ -46,19 +52,23 @@ export const LinksListWidget: FC<LinksListWidgetProps> = ({
* @param {LinksListItems[]} data - The widget data.
* @returns {ListItem[]} The list items data.
*/
- const getListItems = (data: LinksListItems[]): ListItem[] => {
- return data.map((item) => {
- return {
- id: slugify(item.name),
- child: item.child && getListItems(item.child),
- value: (
- <Link href={item.url} className={styles.list__link}>
- {item.name}
- </Link>
- ),
- };
- });
- };
+ const getListItems = (data: LinksListItems[]) =>
+ data.map((item) => (
+ <ListItem className={styles.list__item} key={slugify(item.name)}>
+ <Link className={styles.list__link} href={item.url}>
+ {item.name}
+ </Link>
+ {item.child?.length ? (
+ <List
+ className={`${styles.list} ${styles[listKindClass]} ${className}`}
+ hideMarker
+ isOrdered={isOrdered}
+ >
+ {getListItems(item.child)}
+ </List>
+ ) : null}
+ </ListItem>
+ ));
return (
<Widget
@@ -70,10 +80,11 @@ export const LinksListWidget: FC<LinksListWidgetProps> = ({
>
<List
className={`${styles.list} ${styles[listKindClass]} ${className}`}
- items={getListItems(items)}
- itemsClassName={styles.list__item}
- kind={kind}
- />
+ hideMarker
+ isOrdered={isOrdered}
+ >
+ {getListItems(items)}
+ </List>
</Widget>
);
};
diff --git a/src/components/organisms/widgets/social-media.module.scss b/src/components/organisms/widgets/social-media.module.scss
index b7191be..1cd3f57 100644
--- a/src/components/organisms/widgets/social-media.module.scss
+++ b/src/components/organisms/widgets/social-media.module.scss
@@ -1,10 +1,5 @@
@use "../../../styles/abstracts/placeholders";
.list {
- @extend %reset-list;
-
- display: flex;
- flex-flow: row wrap;
- gap: var(--spacing-xs);
padding: 0 var(--spacing-2xs);
}
diff --git a/src/components/organisms/widgets/social-media.tsx b/src/components/organisms/widgets/social-media.tsx
index 40513f8..f9dea58 100644
--- a/src/components/organisms/widgets/social-media.tsx
+++ b/src/components/organisms/widgets/social-media.tsx
@@ -1,5 +1,5 @@
-import { FC } from 'react';
-import { SocialLink, type SocialLinkProps } from '../../atoms';
+import type { FC } from 'react';
+import { List, ListItem, SocialLink, type SocialLinkProps } from '../../atoms';
import { Widget, type WidgetProps } from '../../molecules';
import styles from './social-media.module.scss';
@@ -21,17 +21,18 @@ export const SocialMedia: FC<SocialMediaProps> = ({ media, ...props }) => {
* @param {SocialMedia[]} links - An array of social media name and url.
* @returns {JSX.Element[]} The social links.
*/
- const getItems = (links: Media[]): JSX.Element[] => {
- return links.map((link, index) => (
- <li key={`media-${index}`}>
+ const getItems = (links: Media[]): JSX.Element[] =>
+ links.map((link, index) => (
+ <ListItem key={`media-${index}`}>
<SocialLink name={link.name} url={link.url} />
- </li>
+ </ListItem>
));
- };
return (
<Widget expanded={true} {...props}>
- <ul className={styles.list}>{getItems(media)}</ul>
+ <List className={styles.list} hideMarker isInline spacing="xs">
+ {getItems(media)}
+ </List>
</Widget>
);
};
diff --git a/src/components/organisms/widgets/table-of-contents.stories.tsx b/src/components/organisms/widgets/table-of-contents.stories.tsx
index 3078e35..d464715 100644
--- a/src/components/organisms/widgets/table-of-contents.stories.tsx
+++ b/src/components/organisms/widgets/table-of-contents.stories.tsx
@@ -1,4 +1,4 @@
-import { ComponentMeta, ComponentStory } from '@storybook/react';
+import type { ComponentMeta, ComponentStory } from '@storybook/react';
import { TableOfContents as ToCWidget } from './table-of-contents';
/**
@@ -26,7 +26,8 @@ const Template: ComponentStory<typeof ToCWidget> = (args) => (
<ToCWidget {...args} />
);
-const GetWrapper = () => {
+/* eslint-disable max-statements */
+const getWrapper = () => {
const wrapper = document.createElement('div');
const firstTitle = document.createElement('h2');
const firstParagraph = document.createElement('p');
@@ -50,5 +51,5 @@ const GetWrapper = () => {
*/
export const TableOfContents = Template.bind({});
TableOfContents.args = {
- wrapper: GetWrapper(),
+ wrapper: getWrapper(),
};
diff --git a/src/components/organisms/widgets/table-of-contents.tsx b/src/components/organisms/widgets/table-of-contents.tsx
index 0e8789a..e67b495 100644
--- a/src/components/organisms/widgets/table-of-contents.tsx
+++ b/src/components/organisms/widgets/table-of-contents.tsx
@@ -1,4 +1,4 @@
-import { FC } from 'react';
+import type { FC } from 'react';
import { useIntl } from 'react-intl';
import { useHeadingsTree, type Heading } from '../../../utils/hooks';
import { type LinksListItems, LinksListWidget } from './links-list-widget';
@@ -31,21 +31,20 @@ export const TableOfContents: FC<TableOfContentsProps> = ({ wrapper }) => {
* @param {Heading[]} tree - The headings tree.
* @returns {LinksListItems[]} The list items.
*/
- const getItems = (tree: Heading[]): LinksListItems[] => {
- return tree.map((heading) => {
+ const getItems = (tree: Heading[]): LinksListItems[] =>
+ tree.map((heading) => {
return {
name: heading.title,
url: `#${heading.id}`,
child: getItems(heading.children),
};
});
- };
return (
<LinksListWidget
className={styles.list}
+ isOrdered
items={getItems(headingsTree)}
- kind="ordered"
level={2}
title={title}
/>