aboutsummaryrefslogtreecommitdiffstats
path: root/src/components
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-11-22 17:45:03 +0100
committerArmand Philippot <git@armandphilippot.com>2023-11-22 17:46:32 +0100
commit0ac690339083f01a0b12a74ec117eeccd055e932 (patch)
tree539ffee3b35b086a8c035e5abc916ab603fe0001 /src/components
parentd4045fbcbfa8208ec31539744417f315f1f6fad8 (diff)
refactor(components,pages): extract MDX components mapping from pages
Instead of repeating the overriding on each pages, we should define it in one place and reuse it in pages. By default it is not possible to override native HTML tags with MDX so I added a plugin in next config to allow it.
Diffstat (limited to 'src/components')
-rw-r--r--src/components/atoms/figure/figure.tsx2
-rw-r--r--src/components/atoms/heading/heading.tsx2
-rw-r--r--src/components/atoms/lists/list/list.tsx12
-rw-r--r--src/components/mdx.tsx90
4 files changed, 98 insertions, 8 deletions
diff --git a/src/components/atoms/figure/figure.tsx b/src/components/atoms/figure/figure.tsx
index 4dd5b10..7d63259 100644
--- a/src/components/atoms/figure/figure.tsx
+++ b/src/components/atoms/figure/figure.tsx
@@ -11,7 +11,7 @@ export type FigureProps = Omit<HTMLAttributes<HTMLElement>, 'children'> & {
/**
* The contents (ie. an image, illustration, diagram, code snippet, etc.).
*/
- children: ReactNode;
+ children?: ReactNode;
/**
* A figure caption.
*/
diff --git a/src/components/atoms/heading/heading.tsx b/src/components/atoms/heading/heading.tsx
index 6cdb578..d8c58d1 100644
--- a/src/components/atoms/heading/heading.tsx
+++ b/src/components/atoms/heading/heading.tsx
@@ -14,7 +14,7 @@ export type HeadingProps = HTMLAttributes<HTMLHeadingElement> & {
/**
* The heading body.
*/
- children: ReactNode;
+ children?: ReactNode;
/**
* Use an heading element or only its styles.
*
diff --git a/src/components/atoms/lists/list/list.tsx b/src/components/atoms/lists/list/list.tsx
index 6e58433..61d2216 100644
--- a/src/components/atoms/lists/list/list.tsx
+++ b/src/components/atoms/lists/list/list.tsx
@@ -16,14 +16,14 @@ type UnorderedListProps = Omit<HTMLAttributes<HTMLUListElement>, 'children'>;
type BaseListProps<O extends boolean, H extends boolean> = O extends true
? OrderedListProps
: H extends true
- ? OrderedListProps
- : UnorderedListProps;
+ ? OrderedListProps
+ : UnorderedListProps;
type AdditionalProps<O extends boolean, H extends boolean> = {
/**
- * An array of list items.
+ * The list items.
*/
- children: ReactNode;
+ children?: ReactNode;
/**
* Should the items marker be hidden?
*
@@ -109,8 +109,8 @@ const ListWithRef = <O extends boolean, H extends boolean>(
O extends true
? HTMLOListElement
: H extends true
- ? HTMLOListElement
- : HTMLUListElement
+ ? HTMLOListElement
+ : HTMLUListElement
>
) => {
const itemSpacing = spacing === null ? 0 : `var(--spacing-${spacing})`;
diff --git a/src/components/mdx.tsx b/src/components/mdx.tsx
new file mode 100644
index 0000000..f11dda5
--- /dev/null
+++ b/src/components/mdx.tsx
@@ -0,0 +1,90 @@
+import type { MDXComponents } from 'mdx/types';
+import NextImage from 'next/image';
+import type { AnchorHTMLAttributes, ImgHTMLAttributes, ReactNode } from 'react';
+import { Figure, Heading, Link, List, ListItem } from './atoms';
+import { Code, Grid } from './molecules';
+
+const Anchor = ({
+ children = '',
+ href = '',
+ hrefLang,
+ rel,
+ ...props
+}: AnchorHTMLAttributes<HTMLAnchorElement>) => (
+ <Link
+ {...props}
+ isExternal={rel?.includes('external')}
+ href={href}
+ lang={hrefLang}
+ rel={rel}
+ >
+ {children}
+ </Link>
+);
+
+const Img = ({
+ alt,
+ src,
+ height,
+ placeholder,
+ width,
+ ...props
+}: ImgHTMLAttributes<HTMLImageElement>) => {
+ if (src)
+ return (
+ <NextImage
+ {...props}
+ alt={alt ?? ''}
+ height={typeof height === 'string' ? Number(height) : height}
+ src={src}
+ width={typeof width === 'string' ? Number(width) : width}
+ />
+ );
+
+ // eslint-disable-next-line @next/next/no-img-element
+ return <img {...props} alt={alt} height={height} src={src} width={width} />;
+};
+
+const Gallery = ({ children }: { children: ReactNode[] }) => (
+ <Grid
+ // eslint-disable-next-line react/jsx-no-literals
+ gap="sm"
+ items={children.map((child, index) => {
+ return { id: `${index}`, item: child };
+ })}
+ // eslint-disable-next-line react/jsx-no-literals
+ sizeMin="250px"
+ />
+);
+
+export const mdxComponents: MDXComponents = {
+ a: Anchor,
+ Code,
+ figure: ({ ref, ...props }) => <Figure {...props} />,
+ Figure,
+ Gallery,
+ h1: ({ ref, ...props }) => <Heading {...props} level={1} />,
+ h2: ({ ref, ...props }) => <Heading {...props} level={2} />,
+ h3: ({ ref, ...props }) => <Heading {...props} level={3} />,
+ h4: ({ ref, ...props }) => <Heading {...props} level={4} />,
+ h5: ({ ref, ...props }) => <Heading {...props} level={5} />,
+ h6: ({ ref, ...props }) => <Heading {...props} level={6} />,
+ img: Img,
+ li: ({ ref, ...props }) => <ListItem {...props} />,
+ Link,
+ ol: ({ ref, ...props }) => (
+ <List
+ // eslint-disable-next-line react/jsx-no-literals
+ spacing="2xs"
+ {...props}
+ isOrdered
+ />
+ ),
+ ul: ({ ref, ...props }) => (
+ <List
+ // eslint-disable-next-line react/jsx-no-literals
+ spacing="2xs"
+ {...props}
+ />
+ ),
+};