Code Block MDX with Prismjs

Create an MDX Code Block component using Prismjs.js for syntax highlighting.

ReactMDXPrismjsComponents

Preview

import type { ComponentProps } from "react";

const MyComponent = (props: ComponentProps<"div">) => {
  return <div {...props}>Hello, World!</div>;
};

export default MyComponent;

Installation

shadcn/ui

shadcn/ui Command
pnpm dlx shadcn@latest add https://code-blocks.pheralb.dev/r/mdx-prismjs.json

Manual

Before creating the component, make sure you have the basic structure:

Code Block

The main structure of the Code Block component with header and content areas.

  1. Create your Prismjs highlighter utility:

Prismjs Highlighter

The main highlighter utility to render syntax highlighted code with Prismjs.

  1. Create the MDX Prismjs component:
mdx-prismjs
import type { ComponentProps } from "react";
import type { MDXComponents } from "mdx/types";

import { reactToText } from "@/utils/react-to-text";
import { highlight, type Languages } from "@/utils/prismjs/highlight";

import {
  CodeBlock,
  CodeBlockContent,
} from "@/components/code-block/code-block";
import { CopyButton } from "@/components/code-block/copy-button";

type PreProps = ComponentProps<"pre"> & {
  ["data-language"]?: string;
};

const PrePrismComponent: MDXComponents = {
  pre: ({ children, ...props }: PreProps) => {
    const content = reactToText(children);
    const language = props["data-language"] as Languages;
    const codeHTML = highlight({ code: content, language });
    return (
      <CodeBlock className="group/code-block">
        <CodeBlockContent className="relative">
          <CopyButton
            content={content}
            className="sticky top-3 right-3 z-50 float-right rounded-md text-neutral-950 opacity-0 transition-opacity group-hover/code-block:opacity-100 hover:opacity-70 dark:text-neutral-50"
          />
          <pre className="prism-pre">
            <code dangerouslySetInnerHTML={{ __html: codeHTML }} />
          </pre>
        </CodeBlockContent>
      </CodeBlock>
    );
  },
};

export { PrePrismComponent };

Usage

In your MDX Components object, add the PrePrismComponent component:

import type { MDXComponents as MDXComponentsType } from "mdx/types";

import { PrePrismComponent } from "@/components/code-block/mdx/pre-prismjs";

const MDXComponents: MDXComponentsType = {
  ...PrePrismComponent,
};