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 { Toolbar, LineNumbers, CodeBlock, Tokens } 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

CodeBlock

({ shouldAnalyze, unfocusedLinesOpacity, ...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

({ children, ...props }: React.ComponentProps<NonNullable<MDXComponents["pre"]>>) => any

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

Parameters

*

any
Returns
any

CodeBlockProps

CodeBlockProps
Properties

children *

React.ReactNode

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

path

string | undefined

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 | undefined

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 | undefined

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 | undefined

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

focusedLines

string | undefined

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

unfocusedLinesOpacity

number | undefined

Opacity of unfocused lines when using focusedLines.

allowCopy

string | boolean | undefined

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

allowErrors

string | boolean | undefined

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

showErrors

boolean | undefined

Show or hide error diagnostics.

showLineNumbers

boolean | undefined

Show or hide line numbers.

showToolbar

boolean | undefined

Show or hide the toolbar.

shouldAnalyze

boolean | undefined

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

shouldFormat

boolean | undefined

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; } | undefined

CSS styles to apply to code block elements.

className

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

Class names to apply to code block elements.

style

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

Styles to apply to code block elements.

:#637777}\"],[\"hj42to8\",\".hj42to8{font-style:italic}\"]],[]],\"n\":\"$undefined\"}]]}]],null]}]]}]\n"])