CodeBlock
A lightweight syntax-highlighted code block with copy-to-clipboard, line numbers, and automatic dark mode support. Zero external dependencies for syntax highlighting.
import { CodeBlock } from "@ninna-ui/code-block"pnpm add @ninna-ui/code-blockRequires @ninna-ui/core (auto-installed) + CSS setup.
Usage
Import and use the CodeBlock component to display syntax-highlighted code.
1. Install
pnpm add @ninna-ui/code-block2. Add CSS import
/* your CSS entry point (e.g. src/index.css) */@import "tailwindcss";@import "@ninna-ui/core/theme/presets/default.css";
/* Code block syntax token colors */@import "@ninna-ui/code-block/styles";The @import "@ninna-ui/code-block/styles" line loads the syntax token CSS custom properties. Without it the code block renders but syntax colors will be missing.
3. Use
import { CodeBlock } from "@ninna-ui/code-block";
const code = `import { Button } from "@ninna-ui/primitives";
export default function App() { return <Button color="primary">Click me</Button>;}`;
export default function Example() { return <CodeBlock code={code} />;}Basic
A simple code block with TSX syntax highlighting and copy button.
import { Button } from "@ninna-ui/primitives";
export default function App() { return <Button color="primary">Click me</Button>;}Line Numbers
Enable line numbers for longer code snippets.
1import { useState } from "react";2import { Button, Heading, Text } from "@ninna-ui/primitives";3import { Alert } from "@ninna-ui/feedback";4import { VStack } from "@ninna-ui/layout";5
6export default function App() {7 const [count, setCount] = useState(0);8
9 return (10 <VStack gap={4} className="p-8">11 <Heading as="h1" size="3xl">Counter: {count}</Heading>12 <Text className="text-base-content/70">Click to increment.</Text>13 <Button color="primary" onClick={() => setCount(c => c + 1)}>14 Increment15 </Button>16 {count > 5 && (17 <Alert color="success" variant="soft">18 You clicked more than 5 times!19 </Alert>20 )}21 </VStack>22 );23}Without Copy Button
Hide the copy button for read-only display.
pnpm add @ninna-ui/primitives @ninna-ui/code-blockCSS / Multi-language
The highlighter handles CSS, HTML, and mixed content alongside TSX.
1/* Custom theme with oklch colors */2:root,3[data-theme="my-brand"] {4 color-scheme: light;5
6 --color-primary: oklch(0.55 0.20 250);7 --color-primary-content: oklch(0.97 0.01 250);8
9 --color-base-100: oklch(1.0 0 0);10 --color-base-content: oklch(0.21 0.021 260);11}Always Visible Copy
Keep the copy button visible at all times instead of only on hover.
pnpm add @ninna-ui/primitives @ninna-ui/code-blockPlain Text (No Highlight)
Use language="bash" or language="text" to disable syntax highlighting.
1$ pnpm add @ninna-ui/primitives2$ pnpm dev3 ➜ Local: http://localhost:5173/4 ➜ press h + enter to show helpColor Scheme
Force light or dark syntax colors regardless of the current page theme. Useful when embedding a CodeBlock inside a section that has a different background.
colorScheme="light" (always light)
import { useState } from "react";import { Button } from "@ninna-ui/primitives";
export default function Counter() { const [count, setCount] = useState(0); return ( <Button onClick={() => setCount(c => c + 1)}> Count: {count} </Button> );}colorScheme="dark" (always dark)
import { useState } from "react";import { Button } from "@ninna-ui/primitives";
export default function Counter() { const [count, setCount] = useState(0); return ( <Button onClick={() => setCount(c => c + 1)}> Count: {count} </Button> );}colorScheme="auto" (follows page theme)
import { useState } from "react";import { Button } from "@ninna-ui/primitives";
export default function Counter() { const [count, setCount] = useState(0); return ( <Button onClick={() => setCount(c => c + 1)}> Count: {count} </Button> );}Custom Styles
Customize the appearance with className.
const greeting = "Hello, world!";console.log(greeting);const greeting = "Hello, world!";console.log(greeting);API Reference
Complete list of props for the CodeBlock component.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
code* | string | - | The code string to display with syntax highlighting |
language | 'tsx' | 'jsx' | 'typescript' | 'javascript' | 'css' | 'html' | 'json' | 'bash' | 'text' | 'tsx' | Language for syntax highlighting. Use 'text' or 'bash' for no highlighting. |
colorScheme | 'light' | 'dark' | 'auto' | 'auto' | Force a specific syntax color scheme. 'auto' follows the page theme, 'light' always uses light colors, 'dark' always uses dark colors. |
showLineNumbers | boolean | false | Show line numbers in the gutter |
showCopyButton | boolean | true | Show a copy-to-clipboard button (visible on hover by default) |
copyButtonAlwaysVisible | boolean | false | Always show the copy button instead of only on hover |
className | string | - | Additional CSS classes for the root container |
aria-label | string | - | Accessible label for the code block container |
Accessibility
- Uses semantic
preandcodeelements for proper screen reader announcement - Supports
aria-labeland other ARIA attributes via props spread - Copy button has descriptive
aria-labelthat updates on copy ("Copy code to clipboard" / "Code copied") - Decorative SVG icons use
aria-hidden="true" - Syntax colors meet WCAG AA contrast requirements against both light and dark backgrounds
- Line numbers use
select-noneto prevent accidental copying