<CodeBlock> Component

A formatted code block for displaying lovely lines of code.

Share
Code Editor
<CodeBlock language="shell-session" code={`<span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash"><span class="token builtin class-name">echo</span> <span class="token string">"hello world!"</span></span></span>`} />

Where it's used

0.x.x
Loading 0.x.x releases...
1.x.x
Loading 1.x.x releases...
2.x.x
Loading 2.x.x releases...
3.x.x
Loading 3.x.x releases...
4.x.x
Loading 4.x.x releases...
5.x.x
Loading 5.x.x releases...
6.x.x
Loading 6.x.x releases...

Props

NameDescription
className
string
A className string which will be added to the outer element of this component.
code*
string
A string of highlighted HTML or React elements. These elements will be rendered into a <pre><code> container.

A plain string can be passed, but it will not be highlighted.
language
string
Used to set a global "language-*" className on both the pre and code element, for compatibility with language-specific highlight styles. This value should be identical to the language used to generate the highlighted code.
theme
string
Sets the color theme for the code block. Intended to match light and dark system appearance, for example through CSS @media (prefers-color-scheme).
Options: "light", "dark"
hasBarAbove
boolean
Intended for automatic use in CodeTabs, not meant as a consumer-facing prop. Set to true to remove border rounding from the top of the CodeBlock.
onCopyCallback
function
Optional callback that is called when copy success state changes to true or false. When code is successfully copied using the "Copy" button, it changes to true. If there is an error when copying code, it changes to false.
options
object
Additional options that enable supplementary code-block features.
Object contains nested props, see below:
options.showChrome
boolean
Set to true to display a window chrome bar UI above the code block.
options.highlight
string
Specify line numbers to highlight. Supports a comma-separate list of numbers and number ranges, where number ranges are dash-separated pairs of numbers.

For example: "5" highlights line 5; "2,5" highlights lines 2 and 5; "2-5" highlights lines 2, 3, 4, and 5; "2,6-8,11" highlights line 2, 6, 7, 8 and 11.
options.lineNumbers
boolean
Set to true to display line numbers on the left edge of the code block.
options.showClipboard
boolean
Set to true to show the copy-to-clipboard prompt and functionality.

Using features in MDX via CodeBlockConfig

To support richer configuration of code blocks in MDX, we've created a CodeBlockConfig component, which is available in Learn and Docs MDX contexts.

CodeBlockConfig is a wrapper component, similar to the ImageConfig component in our learn repo. CodeBlockConfig can be used to wrap and configure an individual fenced code block. It supports all of the properties of CodeBlock's options props, as detailed in the props table earlier on this page, with a few notable exceptions:

  • showClipboard is not supported, as the Copy button is shown by default in MDX contexts. Instead, a hideClipboard option is supported.
  • showChrome is not supported, as we currently would like to limit such ornamentation to JSX contexts, such as feature callouts on marketing pages.

Features & guidelines

Overflow

Longer lines of code may take up more space than the available content width. In these cases, code blocks will allow horizontal scrolling to view overflowing code.

Source

```
A line that goes on for a very long time so that it overflows the container in which it is located, which might be a pretty wide container.
```
```
A line that goes on for a very long time so that it overflows the container in which it is located, which might be a pretty wide container.
```

Result

A line that goes on for a very long time so that it overflows the container in which it is located, which might be a pretty wide container.
A line that goes on for a very long time so that it overflows the container in which it is located, which might be a pretty wide container.

Syntax Highlighting

Automatic syntax highlighting is supported in MDX contexts such as Learn and Docs. Syntax highlighting is set through the code fence's infostring, which is the string directly after the opening code fence. You can view a full list of supported syntax slugs and aliases in the refractor README.

Source

```javascript
const foo = 'bar'
function hello() {
  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
```
```javascript
const foo = 'bar'
function hello() {
  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
```

Result

const foo = 'bar'
function hello() {
  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
const foo = 'bar'
function hello() {
  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}

Copy to Clipboard

The copy to clipboard button is useful to our practioners when they need to copy and paste content. In most use-cases the copy to clipboard button is necessary, so this feature is enabled by default on all Learn and Docs pages.

Source

```javascript
// Copy this code!
console.log("Hello world");
```
```javascript
// Copy this code!
console.log("Hello world");
```

Result

// Copy this code!
console.log('Hello world')
// Copy this code!
console.log('Hello world')

In some cases, such as when showing diffs, we might want to hide the copy-to-clipboard functionality. In MDX use cases, use the <CodeBlockConfig /> wrapper component with the hideClipboard prop, as shown below.

Source

<CodeBlockConfig hideClipboard>

```javascript
// Doing stuff you shouldn't copy
function sayHello() {
  console.log("Hello again");
}
```

</CodeBlockConfig>
<CodeBlockConfig hideClipboard>
 
```javascript
// Doing stuff you shouldn't copy
function sayHello() {
  console.log("Hello again");
}
```
 
</CodeBlockConfig>

Result

// Doing stuff you shouldn't copy
function sayHello() {
  console.log('Hello again')
}
// Doing stuff you shouldn't copy
function sayHello() {
  console.log('Hello again')
}
Shell snippet interpretation

Our copy-to-clipboard functionality automatically tries to detect shell snippets, and ensure only commands are copied, rather than all characters rendered in a shell session.

However, there are limitations to what is possible with this feature. To start, detection is fairly primitive - any code starting with a $ character on the first line will be interpreted as a shell snippet when copied. This is intended to allow the display of control characters such as $ and shell output in the code block, while ensuring that when copying the snippet, only the executable part of the snippet is copied to the clipboard.

As a basic example, the following snippet's Copy button should yield echo "hello world" rather than the full contents of the code block:

Source

```shell-session
$ echo "hello world"
hello world
```
```shell-session
$ echo "hello world"
hello world
```

Result

$ echo "hello world"
hello world
$ echo "hello world"
hello world

The following multi-line command will be copied in similar way. Note that when using multi-line commands, subsequent lines such as output or additional commands should be placed in a separate code block, as they will not be copied correctly if they are placed directly after a multi-line command.

Source

```shell-session
$ vault kv put kv-v1/dev/config/mongodb \
        url=foo.example.com:35533 \
        db_name=users \
        username=admin password=passw0rd
```
```shell-session
$ vault kv put kv-v1/dev/config/mongodb \
        url=foo.example.com:35533 \
        db_name=users \
        username=admin password=passw0rd
```

Result

$ vault kv put kv-v1/dev/config/mongodb \
        url=foo.example.com:35533 \
        db_name=users \
        username=admin password=passw0rd
$ vault kv put kv-v1/dev/config/mongodb \
        url=foo.example.com:35533 \
        db_name=users \
        username=admin password=passw0rd

The following multi-command snippet should yield two copied lines, both without the leading $ shell symbol. As well, selecting the code should not copy the shell symbol, or the space after it.

Source

```shell-session
$ brew tap hashicorp/tap
$ brew tap hashicorp/tap/terraform
```
```shell-session
$ brew tap hashicorp/tap
$ brew tap hashicorp/tap/terraform
```

Result

$ brew tap hashicorp/tap
$ brew install hashicorp/tap/terraform
$ brew tap hashicorp/tap
$ brew install hashicorp/tap/terraform

Further examples:

ScenarioSupportedWhat gets copiedExample
Single line commandsβœ…The command will be copied without the leading $.πŸ”—
Multi-line commandsβœ…The multi-line command will be copied, without the leading $. Do not include lines after the multi-line command, such as output or additional commands, as they will not be processed correctly.πŸ”—
Commands with outputβœ…The command will be copied without the leading $ or the output.πŸ”—
Non-shell Snippetsβœ…The entire snippet will be copied.πŸ”—
Single-line commands across multiple linesβœ…Commands will be copied without their leading $ . Lines that do not start in $ will be omitted from the copied snippet.⏳ (none yet, relatively new feature)
Multi-line with multiple commands❌Not supported. Only the first command will be copied.πŸ›‘

Line Numbering

Use line numbers for long code blocks, or when you are calling out specific lines via line highlight.

Source

<CodeBlockConfig lineNumbers>

```javascript
const foo = 'bar'
function hello() {
  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
```

</CodeBlockConfig>
<CodeBlockConfig lineNumbers>
 
```javascript
const foo = 'bar'
function hello() {
  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
```
 
</CodeBlockConfig>

Result

const foo = 'bar'
function hello() {
{/* */}  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
1234const foo = 'bar'
function hello() {
{/* */}  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}

Line Highlighting

Use line highlights to visually call out specific lines. The lineNumbers option should typically be used as well. Note that non-highlighted lines will be dimmed, and will not have syntax highlighting colors applied.

Source

<CodeBlockConfig lineNumbers highlight="3,5">

```javascript
console.log('Hello world!')
console.log('This is a second line.')
// Doing more stuff
function logAThirdLine() {
  console.log('Hello again')
}
```

</CodeBlockConfig>
<CodeBlockConfig lineNumbers highlight="3,5">
 
```javascript
console.log('Hello world!')
console.log('This is a second line.')
// Doing more stuff
function logAThirdLine() {
  console.log('Hello again')
}
```
 
</CodeBlockConfig>

Result

console.log('Hello world!')
console.log('This is a second line.')
// Doing more stuff
function logAThirdLine() {
{/* */}  console.log('Hello again')
}
123456console.log('Hello world!')
console.log('This is a second line.')
// Doing more stuff
function logAThirdLine() {
{/* */}  console.log('Hello again')
}

Heading

Code block headings should use a few actionable words and phrases to ensure efficient scanning and identification. Headings can start to stack and become hard to read at smaller viewports if they are too many characters. Aim for headings with 50 or fewer characters.

Source

<CodeBlockConfig heading="Say hello in English or French">

```javascript
const foo = 'bar'
function hello() {
  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
```

</CodeBlockConfig>
<CodeBlockConfig heading="Say hello in English or French">
 
```javascript
const foo = 'bar'
function hello() {
  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
```
 
</CodeBlockConfig>

Result

const foo = 'bar'
function hello() {
{/* */}  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
Say hello in English or French
const foo = 'bar'
function hello() {
{/* */}  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}

Filename

Add a filename to be shown above the snippet. Filenames should always correspond with an actual curated file that our users will be using or referencing to avoid confusion.

Source

<CodeBlockConfig filename="hello-world.js">

```javascript
const foo = 'bar'
function hello() {
  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
```

</CodeBlockConfig>
<CodeBlockConfig filename="hello-world.js">
 
```javascript
const foo = 'bar'
function hello() {
  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
```
 
</CodeBlockConfig>

Result

const foo = 'bar'
function hello() {
{/* */}  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}
hello-world.js
const foo = 'bar'
function hello() {
{/* */}  return Math.random() > 0.5 ? 'Hello' : 'Bonjour'
}

Multi-language CodeTabs

The CodeTabs component, which is available in Learn and Docs MDX contexts, allows authors to create multi-snippet tabbed code blocks. <CodeTabs> is a wrapper component around child code blocks. Each child must be either a fenced code block, or must be a <CodeBlockConfig> which wraps a fenced code block.

By default, the tab options are shown at the left of the component. When space is limited, tabs will automatically collapse into a dropdown menu. When a heading is provided to CodeTabs, the heading will be shown at left, and the tabs (or dropdown menu) will be shown at right.

CodeTabs Playground

Share
Code Editor
<CodeTabs theme="dark">
<CodeBlock
options={{ showClipboard: true, filename: 'hello-world.js' }}
language="javascript"
code={`<span class="token console class-name">console</span><span class="token punctuation">.</span><span class="token method function property-access">log</span><span class="token punctuation">(</span><span class="token string">'hello world'</span><span class="token punctuation">)</span>`}
/>
<CodeBlock
options={{ showClipboard: true }}
language="go"
code={`<span class="token keyword">package</span> main{/* */}
{/* */}
<span class="token keyword">import</span> <span class="token string">"fmt"</span>
{/* */}
<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
{/* */} fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"hello world"</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>`}
/>
</CodeTabs>

When to use CodeTabs

Tabs should only be used when switching between equivalent approaches to a particular task or workflow. Common examples include alternate configuration type, programming, languages, or operating systems:

  • Windows / macOS / Linux
  • HCL / JSON
  • JavaScript / BASH

With fenced code child tabs

CodeTabs canΒ be used directly with fenced code children.

Source

<CodeTabs>

```javascript
console.log("hello world")
```

```shell
echo "hello world"
```

</CodeTabs>
<CodeTabs>
 
```javascript
console.log("hello world")
```
 
```shell
echo "hello world"
```
 
</CodeTabs>

Result

console.log('hello world')
console.log('hello world')
echo "hello world"
echo "hello world"

With CodeBlockConfig child tabs

CodeTabs can be used with fenced code children wrapped with CodeBlockConfig configuration. Note as well that tabs can be mixed - some tabs can be plain fenced code and others can use CodeBlockConfig.

Source

<CodeTabs heading="Set your primary datacenter">

<CodeBlockConfig filename="consul-acl.hcl" lineNumbers highlight="3,6-8">

```hcl
primary_datacenter = "dc1"
acl {
  enabled        = true
  default_policy = "deny"
  down_policy    = "extend-cache"
  tokens {
    "agent" = "da666809-98ca-0e94-a99c-893c4bf5f9eb"
  }
}
```

</CodeBlockConfig>

<CodeBlockConfig filename="consul-acl.json" lineNumbers highlight="4,7-9">

```json
{
  "primary_datacenter": "dc1",
  "acl": {
    "enabled": true,
    "default_policy": "deny",
    "down_policy": "extend-cache",
    "tokens": {
      "agent": "da666809-98ca-0e94-a99c-893c4bf5f9eb"
    }
  }
}
```

</CodeBlockConfig>

</CodeTabs>
<CodeTabs heading="Set your primary datacenter">
 
<CodeBlockConfig filename="consul-acl.hcl" lineNumbers highlight="3,6-8">
 
```hcl
primary_datacenter = "dc1"
acl {
  enabled        = true
  default_policy = "deny"
  down_policy    = "extend-cache"
  tokens {
    "agent" = "da666809-98ca-0e94-a99c-893c4bf5f9eb"
  }
}
```
 
</CodeBlockConfig>
 
<CodeBlockConfig filename="consul-acl.json" lineNumbers highlight="4,7-9">
 
```json
{
  "primary_datacenter": "dc1",
  "acl": {
    "enabled": true,
    "default_policy": "deny",
    "down_policy": "extend-cache",
    "tokens": {
      "agent": "da666809-98ca-0e94-a99c-893c4bf5f9eb"
    }
  }
}
```
 
</CodeBlockConfig>
 
</CodeTabs>

Result

{
{/* */}  "primary_datacenter": "dc1",
{/* */}  "acl": {
{/* */}    "enabled": true,
{/* */}    "default_policy": "deny",
{/* */}    "down_policy": "extend-cache",
{/* */}    "tokens": {
{/* */}      "agent": "da666809-98ca-0e94-a99c-893c4bf5f9eb"
{/* */}    }
{/* */}  }
}
consul-acl.hcl
1 2 3 4 5 6 7 8 9 1011{
{/* */}  "primary_datacenter": "dc1",
{/* */}  "acl": {
{/* */}    "enabled": true,
{/* */}    "default_policy": "deny",
{/* */}    "down_policy": "extend-cache",
{/* */}    "tokens": {
{/* */}      "agent": "da666809-98ca-0e94-a99c-893c4bf5f9eb"
{/* */}    }
{/* */}  }
}
primary_datacenter = "dc1"
acl {
{/* */}  enabled        = true
{/* */}  default_policy = "deny"
{/* */}  down_policy    = "extend-cache"
{/* */}  tokens {
{/* */}    "agent" = "da666809-98ca-0e94-a99c-893c4bf5f9eb"
{/* */}  }
}
consul-acl.json
123456789primary_datacenter = "dc1"
acl {
{/* */}  enabled        = true
{/* */}  default_policy = "deny"
{/* */}  down_policy    = "extend-cache"
{/* */}  tokens {
{/* */}    "agent" = "da666809-98ca-0e94-a99c-893c4bf5f9eb"
{/* */}  }
}

With arbitary tab names

By default, CodeTabs will automatically set tab headings based on the language used for syntax highlighting in each child tab.

In some cases, we may want to set custom tab headings. This can be done by passing an array of heading strings to CodeTab's tabs prop.

Source

<CodeTabs tabs={[ "macOS", "Windows" ]}>

<CodeBlockConfig filename="hello-world.js">

```javascript
console.log('hello world')
```

</CodeBlockConfig>

```go
package main

import "fmt"

func main() {
  fmt.Println("hello world")
}
```

</CodeTabs>
<CodeTabs tabs={[ "macOS", "Windows" ]}>
 
<CodeBlockConfig filename="hello-world.js">
 
```javascript
console.log('hello world')
```
 
</CodeBlockConfig>
 
```go
package main
 
import "fmt"
 
func main() {
  fmt.Println("hello world")
}
```
 
</CodeTabs>

Result

console.log('hello world')
hello-world.js
console.log('hello world')
package main{/* */}
{/* */}
import "fmt"
{/* */}
func main() {
{/* */}  fmt.Println("hello world")
}
package main{/* */}
{/* */}
import "fmt"
{/* */}
func main() {
{/* */}  fmt.Println("hello world")
}

JSX-only Features

The CodeBlock component supports a few extra features in JSX that are not used in MDX contexts. These features are detailed below.

Window chrome

The options.showChrome prop, which is only available in JSX contexts, allows consumers to display a bar of window-like UI chrome above the code block. This feature is most often used on feature overviews on marketing sites.

import "fmt"

func main() {
 fmt.Println("Hello world!")
}
import "fmt"
 
func main() {
 fmt.Println("Hello world!")
}

Theme

In JSX contexts, the consumer has the option to set the theme of the code block. Note however in the future, the theme prop may be ignored in favour of user preferences for light or dark colour schemes, for example via the @media (prefers-color-scheme) CSS media query.

"dark" theme

Set your primary datacenter
package main

import "fmt"

func main() {
    ch := make(chan float64)
    ch <- 1.0e10    // magic number
    x, ok := <- ch
    defer fmt.Println("exiting now")
    go println(len("hello world!"))
    return
}
hello-world.go
1 2 3 4 5 6 7 8 9 101112package main
 
import "fmt"
 
func main() {
    ch := make(chan float64)
    ch <- 1.0e10    // magic number
    x, ok := <- ch
    defer fmt.Println("exiting now")
    go println(len("hello world!"))
    return
}
primary_datacenter = "dc1"
acl {
{/* */}  enabled        = true
{/* */}  default_policy = "deny"
{/* */}  down_policy    = "extend-cache"
{/* */}  tokens {
{/* */}    "agent" = "da666809-98ca-0e94-a99c-893c4bf5f9eb"
{/* */}  }
}
consul-acl.hcl
123456789primary_datacenter = "dc1"
acl {
{/* */}  enabled        = true
{/* */}  default_policy = "deny"
{/* */}  down_policy    = "extend-cache"
{/* */}  tokens {
{/* */}    "agent" = "da666809-98ca-0e94-a99c-893c4bf5f9eb"
{/* */}  }
}

"light" theme

Set your primary datacenter
package main

import "fmt"

func main() {
    ch := make(chan float64)
    ch <- 1.0e10    // magic number
    x, ok := <- ch
    defer fmt.Println("exiting now")
    go println(len("hello world!"))
    return
}
hello-world.go
1 2 3 4 5 6 7 8 9 101112package main
 
import "fmt"
 
func main() {
    ch := make(chan float64)
    ch <- 1.0e10    // magic number
    x, ok := <- ch
    defer fmt.Println("exiting now")
    go println(len("hello world!"))
    return
}
primary_datacenter = "dc1"
acl {
{/* */}  enabled        = true
{/* */}  default_policy = "deny"
{/* */}  down_policy    = "extend-cache"
{/* */}  tokens {
{/* */}    "agent" = "da666809-98ca-0e94-a99c-893c4bf5f9eb"
{/* */}  }
}
consul-acl.hcl
123456789primary_datacenter = "dc1"
acl {
{/* */}  enabled        = true
{/* */}  default_policy = "deny"
{/* */}  down_policy    = "extend-cache"
{/* */}  tokens {
{/* */}    "agent" = "da666809-98ca-0e94-a99c-893c4bf5f9eb"
{/* */}  }
}

Code passed as JSX or HTML

When rendering highlighted code tokens, the CodeBlock component's code prop can accept either HTML or JSX that represents those tokens. This allows the component to function both in MDX contexts (where JSX tokens are passed) and in JSX contexts (where consumers will likely pass highlighted HTML).

With html code

package main

import "fmt"

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

With jsx code

package main

import  "fmt"

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

import  "fmt"

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