Code Block
A syntax-highlighted code block with CSS-based themes and one-click copy.
Use CodeBlock to display syntax-highlighted code with optional line numbers and clipboard copying. It works in Vue or Nuxt with Tailwind CSS and inherits Nuxt UI colors when available. It uses Shiki directly, with no Nuxt module or application theme state required.
Example
<script setup lang="ts">
const code = `<script setup lang="ts">
const count = ref(0)
<\/script>
<template>
<div class="flex flex-col items-center gap-4 p-8">
<p class="text-lg font-semibold">Count: {{ count }}</p>
<UButton @click="count++">Increment</UButton>
</div>
</template>`
</script>
<template>
<CodeBlock
:code="code"
language="vue"
filename="Counter.vue"
/>
</template>
nuxt-charts add CodeBlock
Props
| Prop | Type | Default | Description |
|---|---|---|---|
code | string | — | The source code to display. |
language | string | 'text' | Language for syntax highlighting (e.g. vue, typescript, bash). |
filename | string | undefined | Filename shown in the header. Falls back to language. |
showLineNumbers | boolean | false | Display line numbers. |
highlighter | 'shiki' | 'lowlight' | 'shiki' | Highlighting engine to use. Both engines work in Vue and Nuxt. |
theme | string | undefined | Explicit Shiki theme. Overrides darkTheme / lightTheme. |
darkTheme | string | 'github-dark' | Shiki theme used in dark color mode. |
lightTheme | string | 'github-light' | Shiki theme used in light color mode. |
maxHeight | string | number | undefined | Max height of the code area (e.g. 400 or '50vh'). Scrollable when exceeded. |
loading | boolean | false | Shows the loading slot instead of code. |
showHeader | boolean | true | Show the filename and copy button header. |
showCopy | boolean | true | Show the copy button when the header is visible. |
copyLabel | string | 'Copy code' | Copy button text and accessible label. |
copiedLabel | string | 'Copied!' | Button text after a successful copy. |
emptyLabel | string | 'No code provided' | Empty state text. |
Theme Support
By default the component automatically switches between github-light and github-dark using the ancestor .dark class. Override per-instance with theme, or set separate darkTheme / lightTheme props:
<template>
<!-- Fixed theme -->
<CodeBlock theme="nord" language="typescript" :code="tsCode" />
<!-- Per color mode -->
<CodeBlock dark-theme="one-dark-pro" light-theme="github-light" language="vue" :code="code" />
</template>
Requirements
Install the highlighting dependencies in your Vue or Nuxt project:
npm install shiki lowlight hast-util-to-html
Both engines are loaded on demand. Unsupported languages or themes fall back to escaped plain text and emit highlight-error.
Presentation and Events
showHeader and showCopy default to true. Set showHeader to false to display only the code. Customize button and empty-state text with copyLabel, copiedLabel, and emptyLabel.
The header slot receives filename and language; loading and empty slots replace those states. The component emits copy with the copied source, copy-error if clipboard access fails, and highlight-error if highlighting fails.
Dual Shiki themes follow the ancestor .dark class through CSS. An explicit theme keeps that theme in both modes. Lowlight uses semantic CSS colors. Clipboard copying requires a secure browser context.