Prism code highlight

Code highlight with Mantine theme colors and styles
Import
License

Installation

Package depends on react, react-dom, @mantine/hooks, @mantine/core and prism-react-renderer.

Install with npm:

npm install @mantine/prism @mantine/core @mantine/hooks

Install with yarn:

yarn add @mantine/prism @mantine/core @mantine/hooks

Usage

Use Prism component to highlight code with Mantine theme styles. Component uses prism-react-renderer under the hood and support light and dark theme, it is used in Mantine docs to display all code examples.

import { Button } from '@mantine/core';
function Demo() {
return <Button>Hello</Button>
}
import { Prism } from '@mantine/prism';
const demoCode = `import { Button } from '@mantine/core';
function Demo() {
return <Button>Hello</Button>
}`;
function Demo() {
return <Prism language="tsx">{demoCode}</Prism>;
}

Line numbers

Set withLineNumbers prop to display line numbers:

1
import { Button } from '@mantine/core';
2
3
function Demo() {
4
return <Button>Hello</Button>
5
}
import { Prism } from '@mantine/prism';
function Demo() {
return <Prism withLineNumbers language="tsx">{/* ...code */}</Prism>;
}

Lines highlight

To highlight individual lines use highlightLines prop with object containing line numbers as keys and highlight options as values. Highlight options include color from theme.colors and label which replaces line number:

1
import { Button } from '@mantine/core';
2
-
function Demo() {
-
return <Button>Hello</Button>
-
}
6
+
function Usage() {
+
return <ActionIcon>Hello</ActionIcon>;
+
}
import { Prism } from '@mantine/prism';
const deleted = { color: 'red', label: '-' };
const added = { color: 'green', label: '+' };
function Demo() {
return (
<Prism
language="tsx"
withLineNumbers
highlightLines={{
3: deleted,
4: deleted,
5: deleted,
7: added,
8: added,
9: added,
}}
>
{/* ...code */}
</Prism>
);
}

Copy button

To remove copy button set noCopy prop. Copy button labels can be changed with copyLabel and copiedLabel props:

import { Button } from '@mantine/core';
function Demo() {
return <Button>Hello</Button>
}
import { Button } from '@mantine/core';
function Demo() {
return <Button>Hello</Button>
}
import { Prism } from '@mantine/prism';
function Demo() {
return (
<>
<Prism noCopy language="tsx">{/* ...code */}</Prism>
<Prism
language="tsx"
copyLabel="Copy code to clipboard"
copiedLabel="Code copied to clipboard"
>
{/* ...code */}
</Prism>
</>
);
}

Native scrollbars

By default, Prism uses ScrollArea component to handle overflow content, to replace it with native scrollbars set scrollAreaComponent="div":

With ScrollArea component (default):
<p>
Long code that will force Prism to have a horizontal scrollbar, by default, scroll behavior is handled by ScrollArea component, but it can be changed to native browser scrollbars
</p>
With native scrollbars:
<p>
Long code that will force Prism to have a horizontal scrollbar, by default, scroll behavior is handled by ScrollArea component, but it can be changed to native browser scrollbars
</p>
import { Text } from '@mantine/core';
import { Prism } from '@mantine/prism';
const longCode = `
<p>
Long code that will force Prism to have a horizontal scrollbar, by default, scroll behavior is handled by ScrollArea component, but it can be changed to native browser scrollbars
</p>
`;
function Demo() {
return (
<>
<Text mb={5}>With ScrollArea component (default):</Text>
<Prism language="tsx">{longCode}</Prism>
<Text mb={5} mt="xl">With native scrollbars:</Text>
<Prism language="tsx" scrollAreaComponent="div">{longCode}</Prism>
</>
);
}

With tabs

To display multiple files use Prism.Tabs component, it supports the same props as Tabs component:

@font-face {
font-family: Chunkfive; src: url('Chunkfive.otf');
}
body, .usertext {
color: #F0F0F0; background: #600;
font-family: Chunkfive, sans;
--heading-1: 30px/32px Helvetica, sans-serif;
}
@import url(print.css);
@media print {
a[href^=http]::after {
content: attr(href)
}
}
import { Prism } from '@mantine/prism';
function CSSIcon(props: React.ComponentProps<'svg'>) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" {...props}>
<path fill="#0277BD" d="M41 5H7l3 34 14 4 14-4 3-34z" />
<path fill="#039BE5" d="M24 8v31.9l11.2-3.2L37.7 8z" />
<path fill="#FFF" d="M33.1 13H24v4h4.9l-.3 4H24v4h4.4l-.3 4.5-4.1 1.4v4.2l7.9-2.6.7-11.5z" />
<path
fill="#EEE"
d="M24 13v4h-8.9l-.3-4H24zm-4.6 8l.2 4H24v-4h-4.6zm.4 6h-4l.3 5.5 7.9 2.6v-4.2l-4.1-1.4-.1-2.5z"
/>
</svg>
);
}
function PythonIcon(props: React.ComponentProps<'svg'>) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" {...props}>
<path
fill="#0277BD"
d="M24.047 5c-1.555.005-2.633.142-3.936.367-3.848.67-4.549 2.077-4.549 4.67V14h9v2H10.87c-2.636 0-4.943 1.242-5.674 4.219-.826 3.417-.863 5.557 0 9.125C5.851 32.005 7.294 34 9.931 34h3.632v-5.104c0-2.966 2.686-5.896 5.764-5.896h7.236c2.523 0 5-1.862 5-4.377v-8.586c0-2.439-1.759-4.263-4.218-4.672.061-.006-1.756-.371-3.298-.365zm-4.984 4c.821 0 1.5.677 1.5 1.502a1.5 1.5 0 01-1.5 1.498 1.49 1.49 0 01-1.5-1.498A1.5 1.5 0 0119.063 9z"
/>
<path
fill="#FFC107"
d="M23.078 43c1.555-.005 2.633-.142 3.936-.367 3.848-.67 4.549-2.077 4.549-4.67V34h-9v-2h13.693c2.636 0 4.943-1.242 5.674-4.219.826-3.417.863-5.557 0-9.125C41.274 15.995 39.831 14 37.194 14h-3.632v5.104c0 2.966-2.686 5.896-5.764 5.896h-7.236c-2.523 0-5 1.862-5 4.377v8.586c0 2.439 1.759 4.263 4.218 4.672-.061.006 1.756.371 3.298.365zm4.985-4c-.821 0-1.5-.677-1.5-1.502a1.5 1.5 0 011.5-1.498c.837 0 1.5.664 1.5 1.498 0 .822-.664 1.502-1.5 1.502z"
/>
</svg>
);
}
function TsIcon(props: React.ComponentProps<'svg'>) {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" {...props}>
<path fill="#1976d2" d="M6 6h36v36H6z" />
<path
fill="#fff"
d="M27.49 22H14.227v3.264h4.757V40h3.769V25.264h4.737zM39.194 26.084s-1.787-1.192-3.807-1.192-2.747.96-2.747 1.986c0 2.648 7.381 2.383 7.381 7.712 0 8.209-11.254 4.568-11.254 4.568V35.22s2.152 1.622 4.733 1.622 2.483-1.688 2.483-1.92c0-2.449-7.315-2.449-7.315-7.878 0-7.381 10.658-4.469 10.658-4.469l-.132 3.509z"
/>
</svg>
);
}
function Demo() {
return (
<Prism.Tabs>
<Prism.Tab label="styles.css" language="css" icon={<CSSIcon />}>
{/* ...cssCode */}
</Prism.Tab>
<Prism.Tab label="decorator.py" language="python" icon={<PythonIcon />}>
{/* ...pythonCode */}
</Prism.Tab>
<Prism.Tab label="component.tsx" language="tsx" icon={<TsIcon />}>
{/* ...tsCode */}
</Prism.Tab>
</Prism.Tabs>
);
}

Force dark/light theme

You can force dark/light color scheme by setting colorScheme prop:

import { Button } from '@mantine/core';
function Demo() {
return <Button>Hello</Button>
}
import { Prism } from '@mantine/prism';
function Demo() {
return <Prism colorScheme="dark" language="tsx">{/* ...code */}</Prism>;
}

Languages

Component supports all languages which are supported by prism-react-renderer:

package main
import "fmt"
func main() {
ch := make(chan float64)
ch <- 1.0e10 // magic number
x, ok := <- ch
defer fmt.Println(`exitting now`)
go println(len("hello world!"))
return
}