Skip to content
omaris

Data Display

CodeBlock

A code block: highlighted, copyable, and themed like everything else.

import { CodeBlock } from 'omaris'
Learn

Examples

Basic

Highlighted with theme tokens rather than a library — no Prism, no Shiki, no innerHTML. Every token is a real element, so it re-hues with everything else and a muted theme gets muted code.

totals.ts TypeScript
import { Button, Card, CardContent } from 'omaris';​export function total(rows: Row[]) {	return rows.reduce((sum, row) => sum + row.amount, 0);}​// A tone is a colour role; a variant is a fill style.const props = { variant: 'tonal', tone: 'success' } as const;
<script lang="ts">	import { CodeBlock } from 'omaris';​	const CODE = `import { Button, Card, CardContent } from 'omaris';​export function total(rows: Row[]) {	return rows.reduce((sum, row) => sum + row.amount, 0);}​// A tone is a colour role; a variant is a fill style.const props = { variant: 'tonal', tone: 'success' } as const;`;</script>​<div class="w-full max-w-xl">	<CodeBlock code={CODE} lang="ts" title="totals.ts" /></div>

Line numbers and highlight

lineNumbers and highlight when the prose beside the block points at a line — "see line 4" needs a 4 on the page.

export function cn(...inputs) {	return twMerge(clsx(inputs));}​// The class prop is merged last, so it always wins.const classes = cn(buttonVariants({ variant }), className);
<script lang="ts">	import { CodeBlock } from 'omaris';​	const CODE = `export function cn(...inputs) {	return twMerge(clsx(inputs));}​// The class prop is merged last, so it always wins.const classes = cn(buttonVariants({ variant }), className);`;</script>​<div class="w-full max-w-xl">	<CodeBlock code={CODE} lang="ts" lineNumbers highlight="5-6" /></div>

Diff and collapse

diff reads the leading + and - as signs rather than code. collapse shows that many lines with a control to open the rest.

vite.config.ts TypeScript
import adapter from '@sveltejs/adapter-auto';import adapter from '@sveltejs/adapter-static';​export default defineConfig({	plugins: [		sveltekit({			adapter: adapter()			adapter: adapter(),			prerender: { handleMissingId: 'fail' }		})	]});
<script lang="ts">	import { CodeBlock } from 'omaris';​	const DIFF = `-import adapter from '@sveltejs/adapter-auto';+import adapter from '@sveltejs/adapter-static';​ export default defineConfig({ 	plugins: [ 		sveltekit({-			adapter: adapter()+			adapter: adapter(),+			prerender: { handleMissingId: 'fail' } 		}) 	] });`;</script>​<div class="w-full max-w-xl">	<CodeBlock code={DIFF} lang="ts" diff collapse={8} title="vite.config.ts" /></div>

Variants

ghost has no frame, for code already inside a bordered surface.

bun add omaris
bun add omaris
bun add omaris
<script lang="ts">	import { CodeBlock } from 'omaris';</script>​<div class="flex w-full max-w-xl flex-col gap-4">	<CodeBlock code="bun add omaris" lang="bash" variant="outlined" />	<CodeBlock code="bun add omaris" lang="bash" variant="filled" />	<CodeBlock code="bun add omaris" lang="bash" variant="ghost" size="sm" copy={false} /></div>

When to use it

Use it for

  • Read-only source: an install line, a config snippet, a response body, the "copy this" in a docs page. Highlighted with the theme's --code-* tokens, with copy on.
  • A file worth pointing at. title="button.svelte", lineNumbers, highlight="2-4", and focus to dim the rest until the block is hovered.
  • A short before and after. diff reads leading + and - as signs and tints the lines.
  • Long output. collapse={12} shows the top and a control for the rest; wrap for a shell command that must not scroll sideways.

Not for

  • Text someone edits → Code Editor.
  • Two versions of a file → Diff Viewer. It diffs inside changed lines and collapses unchanged runs. diff here is for a hand-written five-line change.
  • A payload someone explores → JSON Viewer. lang="json" is right for a short, fixed example.
  • A stream of lines that keeps arriving → Log Viewer.
  • One identifier in a sentence → Text as="code".

Do

  • Set lang: ts, svelte, css, json, bash, python, sql, yaml, md. Every token is a real element, so the code follows the theme.
  • Use variant="ghost" inside a card or a sheet that already has a border, filled on a plain page section. The default outlined stands alone.
  • Keep lineNumbers on when you highlight, and set startLine when the snippet is cut from a file, so the prose can say "line 14" and mean it.
  • Let the block be as tall as its content. collapse is the height control, and it opens with the height animating.

Don't

  • Paste minified or generated code and collapse it. That hides the length, not the noise.
  • Leave copy on a fragment with … or placeholder values in it. People paste what the button gives them.
  • Give it a max-h-* and let it scroll both ways. A block that scrolls inside a page that scrolls is a trap.

Quick reference

variant
  • outlined (default)
  • filled
  • ghost
size
  • sm
  • md (default)

API

CodeBlock

A code block: highlighted, copyable, and themed like everything else.

The colours are tokens (--code-keyword, --code-string, …) defined in both themes and driven by the same chroma knob as the rest of the palette, so a muted theme gets muted code and a re-hued one gets re-hued code. The highlighter is highlight.ts — no Prism, no Shiki, no innerHTML; every token is a real element.

import { CodeBlock } from 'omaris'
<CodeBlock lang="svelte" title="button.svelte" lineNumbers highlight="2-4" {code} />

Parts

Every element this renders is reachable from outside. Pass Tailwind for one part as classes={{ part: '…' }}; class covers the root and is merged last, so it always wins.

root
No description in the source yet.
header
Filename bar: title, language chip, actions.
title
No description in the source yet.
badge
No description in the source yet.
viewport
The scroll container — focusable, so a keyboard can scroll it.
code
No description in the source yet.
line
One line — a row so the gutter can stay put while the code scrolls.
gutter
Line number, pinned against horizontal scroll.
sign
+ / - column, in diff mode.
content
No description in the source yet.
float
The floating copy button when there's no header to hold it.
expand
"Show all" strip under a collapsed block.
fade
The fade that says "there's more below".

Props

code required
string

The source. Leading and trailing blank lines are trimmed.

lang

Defaults to 'plain'

string

ts, svelte, css, json, bash, python, sql, yaml, md, …

title
string

Filename, shown in the header bar.

variant

Defaults to 'outlined'

CodeBlockVariant
outlined
The default — a bordered surface, like a card.
filled
Fills without a border, for use inside an already-bordered surface.
ghost
No container at all — code on the page.
size

Defaults to 'md'

CodeBlockSize
sm
md
badge
boolean

Show the language chip. Defaults to on whenever there's a header.

lineNumbers

Defaults to false

boolean
startLine

Defaults to 1

number

Number the first line is given.

highlight
string | number[]

Lines to call out — [2, 5] or '2,5-8'.

focus

Defaults to false

boolean

Dim every line that isn't called out until the block is hovered.

diff

Defaults to false

boolean

Read +/- prefixes as a diff and tint the lines.

copy

Defaults to true

boolean

Offer the copy button.

wrap

Defaults to false

boolean

Wrap long lines instead of scrolling sideways.

collapse
number

Collapse to this many lines, with a control to open it up.

actions
Snippet

Extra header controls, before the copy button.

oncopy
(code: string) => void

Fires after the source lands on the clipboard.

class
string
classes
CodeBlockClasses

Per-part Tailwind overrides. class still covers the root.