v3.0.0

mui-markdown

Render Markdown / MDX with MUI components — powered by markdown-to-jsx.

npm version npm downloads license
  • Markdown components adapt to your MUI theme automatically
  • Optional syntax highlighting via prism-react-renderer
  • Optional diagram support via mermaid
  • Optional math support via katex
  • Table of contents extraction with extractHeadings
  • GFM task lists rendered with MUI Checkbox, plus native footnote support

Contributors

Hosein Pouyanmehr Et3rnos ardeaf SGrajdean marcveens Alfredo Salzillo Filip Niklas Luke Yoo

Installation

# with npm
npm i mui-markdown@latest

# with yarn
yarn add mui-markdown
Note: mui-markdown v3 requires markdown-to-jsx v9 or newer as a peer dependency. See the CHANGELOG for migration notes if you're upgrading from v2.

Quick Start

The example below renders the h1 tag using the MUI Typography component.

App.jsx
import React from 'react';
import { MuiMarkdown } from 'mui-markdown';

const App = () => {
  return <MuiMarkdown>{`# Hello markdown!`}</MuiMarkdown>;
};

export default App;

A default export is also available (import MuiMarkdown from 'mui-markdown'), but the named import is recommended.

Props

Props available on the MuiMarkdown component. All props are optional.

NameTypeDefault
keyReact.key-
childrenstring-
overrides*MarkdownToJSX.OverridesdefaultOverrides
options*MarkdownToJSX.Options-
codeWrapperStylesCSSProperties-
prismThemePrismThemevsDark
HighlightHighlightComponent-
customTableScrollbarbooleanfalse
hideLineNumbersbooleanfalse
namestring-
copiablebooleanfalse
CopyComponentComponentType<CopyComponentProps>-
copiedLabelstring'Copied!'
copyLabelstring'Copy code'
copyIconReactNode-
copiedIconReactNode-
copyButtonSxSxProps<Theme>-
showFileIconbooleantrue
fileIconReactNode-
FileNameComponentComponentTypeTypography
fileNameSxSxProps<Theme>-
fileNameWrapperSxSxProps<Theme>-
useHighlightThemeBackgroundbooleanfalse
highlightColorstring'info.main'
removedColorstring'error.main'
insertedColorstring'success.main'
enableMermaidbooleanfalse
mermaidConfigMermaidConfig-
Diagram*DiagramComponent-
enableMathbooleanfalse
katexOptionsKatexOptions-
MathComponent*MathBlockComponent-
Notes: You cannot use overrides and options at the same time. Using customTableScrollbar converts tables to client-side components. You must provide the Diagram component if you've enabled mermaid, and the MathComponent if you've enabled math support.

Overrides

Optionally override any tag to use your own component. Spread defaultOverrides to keep the other default overrides.

Override with a regular HTML tag

App.tsx
import React from 'react';
import { MuiMarkdown, defaultOverrides } from 'mui-markdown';

const App = () => {
  return (
    <MuiMarkdown
      overrides={{
        ...defaultOverrides, // Keeps the other default overrides.
        h1: {
          component: 'p',
          props: {
            style: { color: 'red' },
          } as React.HTMLProps<HTMLParagraphElement>,
        },
      }}
    >
      {`# Hello markdown!`}
    </MuiMarkdown>
  );
};

export default App;

In plain JS/JSX, drop the as React.HTMLProps<...> assertion.

Override with your own component

App.tsx
import React from 'react';
import { MuiMarkdown, defaultOverrides } from 'mui-markdown';
import CustomTypography, {
  CustomTypographyProps,
} from './components/CustomTypography';

const App = () => {
  return (
    <MuiMarkdown
      overrides={{
        ...defaultOverrides, // Keeps the other default overrides.
        h1: {
          component: CustomTypography,
          props: {
            // custom props
          } as CustomTypographyProps,
        },
      }}
    >
      {`# Hello markdown!`}
    </MuiMarkdown>
  );
};

export default App;

Options

Parsing options are passed straight through to markdown-to-jsx — see its parsing options documentation.

Note: If you need both overrides and options, put the overrides property inside options. Don't use the overrides and options props together on the MuiMarkdown component.

Code Wrapper Styles

Pass your desired styles for the syntax highlighter component via codeWrapperStyles. These are the defaults:

borderRadius: '0.5rem',
padding: '0.5rem 0.75rem',
overflow: 'auto',

Syntax Highlight

mui-markdown uses prism-react-renderer to highlight code blocks. It's an optional dependency — install it only if you want highlighting:

# with npm
npm i prism-react-renderer

# with yarn
yarn add prism-react-renderer

Then pass Highlight and themes to the component. Change the theme with prismTheme, and hide line numbers with hideLineNumbers:

App.tsx
import React from 'react';
import { MuiMarkdown } from 'mui-markdown';
import { Highlight, themes } from 'prism-react-renderer';

const App = () => {
  return (
    <MuiMarkdown
      Highlight={Highlight}
      themes={themes}
      prismTheme={themes.github}
      hideLineNumbers
    >
      {`# Hello markdown!`}
    </MuiMarkdown>
  );
};

export default App;

When using overrides, get highlighting by passing Highlight, themes, and your theme to getOverrides:

App.tsx
import React from 'react';
import { MuiMarkdown, getOverrides } from 'mui-markdown';
import { Highlight, themes } from 'prism-react-renderer';

const App = () => {
  return (
    <MuiMarkdown
      overrides={{
        ...getOverrides({ Highlight, themes, theme: themes.github }),
        h1: {
          component: 'p',
          props: {
            style: { color: 'red' },
          },
        },
      }}
    >
      {`# Hello markdown!`}
    </MuiMarkdown>
  );
};

export default App;

Enhanced Code Block Features

Advanced code block features for better documentation and code presentation.

FeatureMarkdown AttributeGlobal PropDescription
Line Highlightinghighlighted="1,3-5"-Highlights specific lines with blue background
Removed Linesremoved="2,4"-Shows deletion lines with red background and - prefix
Inserted Linesinserted="3,5-7"-Shows addition lines with green background and + prefix
File Namename="path/file.ts"name="path/file.ts"Displays file name/path above code block
Copy Buttoncopiablecopiable={true}Adds a copy-to-clipboard button
Hide Line NumbershideLineNumbershideLineNumbers={true}Toggles line number visibility

Highlighting important lines

```tsx highlighted="2,4-6"
function Button({ children }) {
  const [clicked, setClicked] = useState(false);

  const handleClick = () => {
    setClicked(true);
  };

  return <button onClick={handleClick}>{children}</button>;
}
```

Showing code diffs

```tsx removed="2" inserted="3"
export async function getUser(id) {
  const url = `/api/user/${id}`;
  const url = `/api/v2/users/${id}`;
  return fetch(url).then((r) => r.json());
}
```

File name with copy button

```tsx name="components/Header.tsx" copiable
export function Header({ title }) {
  return (
    <header>
      <h1>{title}</h1>
    </header>
  );
}
```

Combined features

```tsx name="src/utils/validator.ts" highlighted="4-6" removed="7" inserted="8" copiable hideLineNumbers
export function validateEmail(email: string): boolean {
  const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

  if (!email) {
    return false;
  }
  const trimmedEmail = email.trimEnd();
  const trimmedEmail = email.trim();
  return regex.test(trimmedEmail);
}
```

Line range syntax

The line range parser supports flexible syntax:

  • Single lines: "1" or "1,2,3"
  • Ranges: "1-5" or "1-5,8-10"
  • Mixed: "1,3-5,7,9-12"
Tip: Markdown attributes override global settings, so you can customize individual code blocks while keeping global defaults.

Global Configuration

Set defaults for all code blocks using getOverrides:

App.tsx
import { MuiMarkdown, getOverrides } from 'mui-markdown';
import { Highlight, themes } from 'prism-react-renderer';

const overrides = getOverrides({
  Highlight,
  themes,
  copiable: true, // All code blocks have copy button
  hideLineNumbers: false, // Show line numbers by default
  copiedLabel: 'Copied!', // Customize copy button labels
  copyLabel: 'Copy',
});

function App() {
  return <MuiMarkdown overrides={overrides}>{markdownContent}</MuiMarkdown>;
}

Customization

All visual elements can be customized using MUI theming.

Custom colors

const overrides = getOverrides({
  Highlight,
  themes,
  highlightColor: 'primary.main', // Use theme colors
  removedColor: 'error.dark',
  insertedColor: 'success.light',
});

Custom copy button icons

import ContentCopyIcon from '@mui/icons-material/ContentCopy';
import CheckIcon from '@mui/icons-material/Check';

const overrides = getOverrides({
  Highlight,
  themes,
  copyIcon: <ContentCopyIcon />,
  copiedIcon: <CheckIcon />,
  copyButtonSx: { top: 16, right: 16 }, // Custom positioning
});

Custom copy component

For complete control over the copy button, provide your own component:

import { CopyComponentProps } from 'mui-markdown';
import { IconButton } from '@mui/material';

const CustomCopyButton = ({ handleCopy, code }: CopyComponentProps) => {
  return (
    <IconButton
      onClick={handleCopy}
      sx={{ position: 'absolute', top: 8, right: 8 }}
    >
      Copy {code.split('\n').length} lines
    </IconButton>
  );
};

const overrides = getOverrides({
  Highlight,
  themes,
  CopyComponent: CustomCopyButton,
});

Custom file name display

import FolderIcon from '@mui/icons-material/Folder';

const overrides = getOverrides({
  Highlight,
  themes,
  showFileIcon: true, // Show/hide icon
  fileIcon: <FolderIcon />, // Custom icon
  FileNameComponent: CustomTypography, // Custom component
  fileNameSx: { fontWeight: 'bold' }, // Custom text styles
  fileNameWrapperSx: { backgroundColor: 'primary.light', px: 3 },
  useHighlightThemeBackground: true, // Prism theme background for file name wrapper
});

Diagram Support (Mermaid)

mui-markdown uses mermaid as its diagramming and charting tool. First make sure mermaid is installed, then enable with enableMermaid and provide the Diagram component. Configure via mermaidConfig.

App.tsx
import React from 'react';
import { MuiMarkdown, getOverrides } from 'mui-markdown';
import { Diagram } from 'mui-markdown/client'; // Handles mermaid init and content load
import { Highlight, themes } from 'prism-react-renderer';

const App = () => {
  return (
    <MuiMarkdown
      enableMermaid
      mermaidConfig={{ startOnLoad: true }}
      DiagramComponent={Diagram}
    >
      {/* Markdown content */}
    </MuiMarkdown>
  );
};

export default App;

The Diagram component is a client-side component. You can create your own — it just needs to satisfy (props: DiagramProps) => JSX.Element. The props type is available under mui-markdown and mui-markdown/client.

Math Support (KaTeX)

mui-markdown uses katex to render math blocks. It's an optional dependency, so install it first:

# with npm
npm i katex

# with yarn
yarn add katex

Then enable with the enableMath prop and pass the MathBlock component (or your own satisfying (props: MathBlockProps) => JSX.Element). Don't forget the KaTeX stylesheet.

App.tsx
import React from 'react';
import { MuiMarkdown } from 'mui-markdown';
import { MathBlock } from 'mui-markdown/client'; // Lazy-loads katex on the client
import 'katex/dist/katex.min.css';

const App = () => {
  return (
    <MuiMarkdown enableMath MathComponent={MathBlock}>
      {`
\`\`\`math
E = mc^2
\`\`\`
`}
    </MuiMarkdown>
  );
};

export default App;

Math blocks are written as fenced code blocks with the math language. Pass KaTeX options via katexOptions. Without enableMath, math blocks render as regular code blocks — nothing changes unless you opt in.

Table of Contents Extraction

Use extractHeadings to get the list of headings (text, level, and the same anchor id that MuiMarkdown renders) and build your own table of contents:

App.tsx
import React from 'react';
import { Link, List, ListItem } from '@mui/material';
import { MuiMarkdown, extractHeadings } from 'mui-markdown';

const markdown = `
# Getting Started

## Installation

## Usage
`;

const App = () => {
  const headings = extractHeadings(markdown);

  return (
    <>
      <List>
        {headings.map((heading) => (
          <ListItem key={heading.id} sx={{ pl: heading.level * 2 }}>
            <Link href={`#${heading.id}`}>{heading.text}</Link>
          </ListItem>
        ))}
      </List>
      <MuiMarkdown>{markdown}</MuiMarkdown>
    </>
  );
};

export default App;
Tip: extractHeadings is a pure function (no rendering), so you can also use it on the server or at build time.

Next.js

Use with useMDXComponents

To add mui-markdown to useMDXComponents, either import defaultMdxComponents or use getMdxComponents if you need to override defaults.

mdx-components.ts
import type { MDXComponents } from 'mdx/types';

import { defaultMdxComponents, getMdxComponents } from 'mui-markdown';

// Use getMdxComponents(options) to override defaults!
// const mdxComponents = getMdxComponents();

export function useMDXComponents(components: MDXComponents): MDXComponents {
  return {
    // ...mdxComponents,
    ...defaultMdxComponents,
    ...components,
  };
}