CodeBlock

Renders a code block with tokenized source code, line numbers, and a toolbar.

When targeting JavaScript or TypeScript languages, the provided source code is type-checked and will throw errors that can be optionally displayed. Additionally, the source code will be formatted using prettier if installed and quick info is available when hovering symbols.

Style Overrides

The CodeBlock component can be styled using the, css, className, and style props to target specific descendant components. In most cases, its a good idea to create your own component that wraps the CodeBlock component and applies the style overrides you need:

import {
  type CodeBlockProps,
  CodeBlock as BaseCodeBlock,
  Tokens,
} from 'renoun/components'
import styles from './CodeBlock.module.css'

export function CodeBlock(props: CodeBlockProps) {
  return (
    <BaseCodeBlock
      {...props}
      css={{
        // Clear the default styles
        container: {
          boxShadow: undefined,
          borderRadius: undefined,
        },
        ...props.css,
      }}
      className={{
        container: styles.container,
        token: styles.token,
        ...props.className,
      }}
    />
  )
}

Component Overrides

If you need more customization, the CodeBlock component can be fully overridden by importing it from renoun/components and extending it as needed:

CodeBlock.tsx
import {
  type CodeBlockProps,
  CodeBlock as BaseCodeBlock,
  Tokens,
} from 'renoun/components'

export function CodeBlock({
  children,
  ...props
}: Omit<CodeBlockProps, 'children'> & { children: string }) {
  return (
    <BaseCodeBlock {...props}>
      <pre
        style={{
          whiteSpace: 'pre',
          wordWrap: 'break-word',
          overflow: 'auto',
        }}
      >
        <Tokens>{children}</Tokens>
      </pre>
    </BaseCodeBlock>
  )
}

Formatting

The CodeBlock source text is formatted by default using prettier if it is installed within the workspace. The shouldFormat prop can be used to disable this behavior:

<CodeBlock language="ts" shouldFormat={false}>
  const foo = 'bar'
</CodeBlock>

Examples

  • const beep = 'boop'
    import { CodeBlock } from 'renoun/components'
    
    export function Basic() {
      return <CodeBlock language="ts">const beep = 'boop'</CodeBlock>
    }
  • Type Checking

    View Source
    const a = 1
    a + b
    import { CodeBlock } from 'renoun/components'
    
    export function TypeChecking() {
      return (
        <CodeBlock language="ts" allowCopy={false} allowErrors showErrors>
          const a = 1; a + b;
        </CodeBlock>
      )
    }
  • Ordered

    View Source
    example.ts
    const a = 1
    example.ts
    const a = 1
    const b = 2
    import { CodeBlock } from 'renoun/components'
    
    export function Ordered() {
      return (
        <div style={{ display: 'grid', gap: '2rem' }}>
          <CodeBlock path="01.example.ts">const a = 1;</CodeBlock>
          <CodeBlock path="02.example.ts">const a = 1; const b = 2;</CodeBlock>
        </div>
      )
    }
  • Line Numbering

    View Source
    line-numbers.ts
    1
    2
    3
    4
    5
    const a = 1
    const b = 2
    
    const add = a + b
    const subtract = a - b
    import { CodeBlock } from 'renoun/components'
    
    export function LineNumbering() {
      return (
        <CodeBlock path="line-numbers.ts" showLineNumbers highlightedLines="4">
          {`const a = 1;\nconst b = 2;\n\nconst add = a + b\nconst subtract = a - b`}
        </CodeBlock>
      )
    }
  • Line Highlighting

    View Source
    line-highlight.ts
    const a = 1
    const b = 2
    
    const add = a + b
    const subtract = a - b
    import { CodeBlock } from 'renoun/components'
    
    export function LineHighlighting() {
      return (
        <CodeBlock path="line-highlight.ts" highlightedLines="2, 4">
          {`const a = 1;\nconst b = 2;\n\nconst add = a + b\nconst subtract = a - b`}
        </CodeBlock>
      )
    }
  • Line Focusing

    View Source
    line-focus.ts
    const a = 1
    const b = 2
    
    const add = a + b
    const subtract = a - b
    import { CodeBlock } from 'renoun/components'
    
    export function LineFocusing() {
      return (
        <CodeBlock path="line-focus.ts" focusedLines="2, 4">
          {`const a = 1;\nconst b = 2;\n\nconst add = a + b\nconst subtract = a - b`}
        </CodeBlock>
      )
    }
  • Line Highlight and Focus

    View Source
    line-highlight-and-focus.ts
    const a = 1
    const b = 2
    
    const add = a + b
    const subtract = a - b
    import { CodeBlock } from 'renoun/components'
    
    export function LineHighlightAndFocus() {
      return (
        <CodeBlock
          path="line-highlight-and-focus.ts"
          highlightedLines="2, 4"
          focusedLines="2, 4"
        >
          {`const a = 1;\nconst b = 2;\n\nconst add = a + b\nconst subtract = a - b`}
        </CodeBlock>
      )
    }
  • Tokens Only

    View Source
    const a = 1
    const b = 2
    a + b
    import { Tokens } from 'renoun/components'
    
    export function TokensOnly() {
      return (
        <pre>
          <Tokens language="ts">{`const a = 1\nconst b = 2\na + b`}</Tokens>
        </pre>
      )
    }
  • Custom Styles

    View Source
    ./counter/Counter.tsx
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    'use client'
    import React from 'react'
    import { useCounter } from './useCounter.js'
    
    export default function Counter({ initialCount }: { initialCount: number }) {
      const { count, decrement, increment } = useCounter(initialCount)
      return (
        <div>
          <button onClick={decrement}>-</button>
          <span>{count}</span>
          <button onClick={increment}>+</button>
        </div>
      )
    }
    import { CodeBlock, LineNumbers, Tokens, Toolbar } from 'renoun/components'
    import { dirname, join } from 'node:path'
    import { fileURLToPath } from 'node:url'
    import { readFile } from 'node:fs/promises'
    
    const directoryPath = dirname(fileURLToPath(import.meta.url))
    
    export async function CustomStyles() {
      const code = await readFile(
        join(directoryPath, './counter/Counter.tsx'),
        'utf-8'
      )
    
      return (
        <CodeBlock path="./counter/Counter.tsx" workingDirectory={directoryPath}>
          <div
            style={{
              fontSize: '1rem',
              borderRadius: '0.25rem',
              boxShadow: '0 0 0 1px var(--color-separator)',
            }}
          >
            <Toolbar
              allowCopy
              css={{
                padding: '0.5lh',
                boxShadow: 'inset 0 -1px 0 0 var(--color-separator)',
              }}
            />
            <pre
              style={{
                display: 'grid',
                gridTemplateColumns: 'min-content max-content',
                padding: '0.5lh 0',
                lineHeight: 1.4,
                whiteSpace: 'pre',
                wordWrap: 'break-word',
                overflow: 'auto',
              }}
            >
              <LineNumbers
                css={{
                  padding: '0 0.5lh',
                  backgroundColor: 'var(--color-background)',
                }}
              />
              <code style={{ paddingRight: '0.5lh' }}>
                <Tokens>{code}</Tokens>
              </code>
            </pre>
          </div>
        </CodeBlock>
      )
    }

API Reference

CodeBlockProps

CodeBlockProps
Properties

children *

React.ReactNode

Pass a code string to highlight or override default rendering using Tokens, LineNumbers, and Toolbar components.

path

string

Name or path of the code block. Ordered file names will be stripped from the name e.g. 01.index.tsx becomes index.tsx.

workingDirectory

string

The working directory to use when analyzing the source code. This will read the local file system contents from the workingDirectory joined with the path prop instead of creating a virtual file.

language

Languages

Language of the source code provided to the Tokens component. When path is defined, the file extension will be used to determine the language by default.

highlightedLines

string

A string of comma separated lines and ranges to highlight e.g. '1, 3-5, 7'.

focusedLines

string

A string of comma separated lines and ranges to focus e.g. '6-8, 12'.

unfocusedLinesOpacity

number

Opacity of unfocused lines when using focusedLines.

allowCopy

boolean | string

Show or hide a button that copies the source code to the clipboard. Accepts a boolean or a string that will be copied.

allowErrors

boolean | string

Whether or not to allow errors. Accepts a boolean or comma-separated list of allowed error codes.

showErrors

boolean

Show or hide error diagnostics.

showLineNumbers

boolean

Show or hide line numbers.

showToolbar

boolean

Show or hide the toolbar.

shouldAnalyze

boolean

Whether or not to analyze the source code for type errors and provide quick information on hover.

shouldFormat

boolean

Whether or not to format the source code using prettier if installed.

css

{ container?: CSSObject; toolbar?: CSSObject; lineNumbers?: CSSObject; token?: CSSObject; popover?: CSSObject; copyButton?: CSSObject; }

CSS styles to apply to code block elements.

container

CSSObject

toolbar

CSSObject

lineNumbers

CSSObject

token

CSSObject

popover

CSSObject

copyButton

CSSObject

className

{ container?: string; toolbar?: string; lineNumbers?: string; token?: string; popover?: string; copyButton?: string; }

Class names to apply to code block elements.

container

string

toolbar

string

lineNumbers

string

token

string

popover

string

copyButton

string

style

{ container?: React.CSSProperties; toolbar?: React.CSSProperties; lineNumbers?: React.CSSProperties; token?: React.CSSProperties; popover?: React.CSSProperties; copyButton?: React.CSSProperties; }

Styles to apply to code block elements.

container

React.CSSProperties

toolbar

React.CSSProperties

lineNumbers

React.CSSProperties

token

React.CSSProperties

popover

React.CSSProperties

copyButton

React.CSSProperties

CodeBlock

(props: CodeBlockProps) => React.JSX.Element

Renders a code block with tokenized source code, line numbers, and a toolbar.

When targeting JavaScript or TypeScript languages, the provided source code is type-checked and will throw errors that can be optionally displayed. Additionally, the source code will be formatted using prettier if installed and quick info is available when hovering symbols.

Parameters
CodeBlockProps
Returns
Element

parsePreProps

(props: React.ComponentProps<"pre">) => { children: string; language?: Languages; } & Omit<React.ComponentProps<"pre">, "children" | "className" | "style">

Parses the props of an MDX pre element for passing to CodeBlock.

Parameters

props *

React.DetailedHTMLProps<React.HTMLAttributes<HTMLPreElement>, HTMLPreElement>
Returns
{ children: string; language?: Languages | undefined; } & Omit<DetailedHTMLProps<HTMLAttributes<HTMLPreElement>, HTMLPreElement>, "style" | ... 1 more ... | "children">