Creating a custom React component to use in the (mdx) blog
- Updated on
MDX's power comes from the ability to create custom components that can be used in the markdown files. This allows you to create resusable sections to display images, layouts or even more advanced visualizations.
Adding a component to the Shipixen blog follows these steps in general:
- create a React component
- import component in MDXComponents.tsx
- use component in markdown file
Let's walk through a couple examples.
Protip
component
Example 1 - adding a Let's add a component that displays an important tip. We can use these in most blog articles to highlight important information.
Example 1 - Creating the component
Start by creating a new React component under components/blog/Protip.tsx
:
import { cn } from '@/lib/utils';
import { SparklesIcon } from 'lucide-react';
export const Protip = ({
className,
title,
description,
}: {
className?: string;
title?: string;
description: string;
}) => {
return (
<div
className={cn(
'flex flex-col text-sm p-6 bg-primary-100/30 dark:bg-purple-900/30 rounded-md',
className,
)}
>
{title ? <p className="m-0 text-lg font-semibold">{title}</p> : null}
<p className="flex gap-1 items-center my-2">
<SparklesIcon className="inline-block w-4 h-4 text-primary-500 dark:text-primary-400" />
{description}
</p>
</div>
);
};
We can use this component by passing a title
and description
prop. For example:
<Protip
title="Heads up!"
description="This is a protip. A little bit of extra attention. It usually contains a useful piece of information."
/>
It'll look something like this:
Heads up!
This is a protip. A little bit of extra attention. It usually contains a useful piece of information.
Example 1 - Adding the component to MDXComponents.tsx
For this component to be available in the blog, we need to register it in components/MDXComponents.tsx
:
import TOCInline from '@shipixen/pliny/ui/TOCInline';
import Pre from '@shipixen/pliny/ui/Pre';
import BlogNewsletterForm from '@shipixen/pliny/ui/BlogNewsletterForm';
import type { MDXComponents } from 'mdx/types';
import Image from './shared/Image';
import CustomLink from './shared/Link';
+ import { Protip } from '@/components/blog/Protip';
export const components: MDXComponents = {
Image,
TOCInline,
a: CustomLink,
pre: Pre,
BlogNewsletterForm,
+ Protip,
};
Example 1 - Using the component in a markdown file
Now the easy part. We can use the component in any markdown file without importing it. Any .mdx file will pick it up automatically!
[...]
Example of markdown file usage.
<Protip
title="Heads up!"
description="This is a protip. A little bit of extra attention. It usually contains a useful piece of information."
/>
[...]
That's it! You now know how to create a custom component for the blog.
Example 2 - adding a dougnut chart
In this example we'll create a component that displays a doughnut chart. We'll use react-chartjs-2 to create the chart.
Example 2 - Creating the component
Start by creating a new React component under components/blog/DoughnutChart.tsx
:
'use client';
import { Doughnut } from 'react-chartjs-2';
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';
ChartJS.register(ArcElement, Tooltip, Legend);
const DonutChart = ({ data }) => {
return <Doughnut data={data} />;
};
export default Doughnut;
Since the underlying Doughnut
component uses React hooks, we add the 'use client'
directive to specify that it is a client side component. Also, there is an existing issue which prevents named components from being used, so we need to export the component as the default export.
Example 2 - Adding the component to MDXComponents.tsx
For this component to be available in the blog, we need to register it in components/MDXComponents.tsx
:
...
+ import DonutChart from './DonutChart'
export const components: MDXComponents = {
Image,
TOCInline,
a: CustomLink,
pre: Pre,
BlogNewsletterForm,
+ DonutChart,
}
Example 2 - Using the component in a markdown file
You can now use the component in any markdown file without importing it. Any .mdx file will pick it up automatically!
[...]
## Example Donut Chart
export const data = {
labels: ['Red', 'Blue', 'Yellow'],
datasets: [
{
label: '# of Votes',
data: [12, 19, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
],
borderWidth: 1,
},
],
};
<DonutChart data={data} />
[...]