Skip to content
ilinxa/pro-ui

Code Block

alphav0.1.4

Code surface with view, edit, and terminal modes — Shiki highlighting, dual-theme CSS variables, and chrome presets for docs, chat, and terminal UIs.

Category: CodeUpdated: 2026-08-11Created: 2026-05-10Author: ilinxa

Context

Substrate for every 'render code professionally' surface in the library — chat assistants, fenced markdown blocks, JSON / config viewers, card-tree code sections, virtual terminal walkthroughs, and snippet editors. View mode uses Shiki's GitHub Light + GitHub Dark Default themes (toggled via the active `.dark` class with zero re-tokenize). Edit mode wraps a CodeMirror 6 instance with a custom HighlightStyle approximating the same GitHub palette (near-match in v0.1.0; pixel-perfect Shiki → CodeMirror bridge defers to v0.2.0). Terminal mode renders structured `TerminalLine[]` rows with prompt detection on `$ `, `> `, `# ` prefixes and macOS-style traffic-light decoration. Streaming-friendly via an explicit `streaming` flag that batches re-tokenization to rAF and shows a blinking tail cursor. Filename → lang derivation works out of the box for ~30 extensions; consumer can override via `filenameToLang`. Object-shape callbacks throughout (per F-cross-12).

Installation

Initialize shadcn (once per project)Seeds lib/utils.ts and components.json. Skip if you've already used any shadcn component.
pnpm dlx shadcn@latest init
Register the @ilinxa namespace (once per project)Add to your components.json. Merge with existing config.
"registries": {
  "@ilinxa": "https://ui.ilinxa.com/r/{name}.json"
}
Install the component
pnpm dlx shadcn@latest add @ilinxa/code-block

Add -fixtures for dummy data:

pnpm dlx shadcn@latest add @ilinxa/code-block-fixtures

Preview

1. View mode — TypeScript (the default)

Filename + language pill + copy button. GitHub Light / Dark token palette.

counter.tsxtsx

2. Line highlights + annotations

Highlighted rows draw the eye; severity icons in the gutter open tooltips with messages.

counter.tsxtsx

3. Streaming — chat assistant style

Click Replay to emit 10-char chunks at 50 ms intervals. Tail cursor blinks while streaming; tokenization stays smooth.

Click to start
counter.tsxtsx

4. JSON config + long-block collapse

Long blocks fade out with a 'Show all' button. Click to expand inline.

package.jsonjson

5. Terminal — virtual install walkthrough

Structured `lines: TerminalLine[]` API. Input rows show the prompt; output rows are muted; error rows in destructive red. macOS traffic-light decoration optional.

zshbash
$ pnpm install
Resolving dependencies...
Adding 247 packages from 38 contributors...
✓ Done in 8.3s
$ pnpm dev
 
▲ Next.js 16.2.0 (Turbopack)
- Local: http://localhost:3000
- Network: http://192.168.1.4:3000
 
✓ Ready in 1.1s
$ pnpm build
✗ Failed to compile
Type error: Property 'foo' does not exist on type 'Bar'

6. Edit mode — controlled CodeMirror editor

Same JetBrains Mono font, same line-height, near-match token colors via custom CodeMirror HighlightStyle. v0.2.0 will swap in a pixel-perfect Shiki bridge.

greet.tsts
Press Cmd/Ctrl+S to save.

7. Custom header — action slot

The header `actions` slot accepts any ReactNode; pre-built buttons (copy, wrap, expand) compose around it.

run-me.tsts

8. Python sample — multi-language coverage

Shiki loads grammars on demand; common languages stay synchronously bundled (~10), the rest dynamic-import.

users.pypython

9. Error trace — annotations on a plain log

`lang='plaintext'` works as a viewer for arbitrary text. Combine with annotations + line-highlights for a debug surface.

stderr.log

10. Inline JSON (no chrome)

`header={false}` for a minimal embed.

Demo source

demo.tsxtsx

Usage

When to use

CodeBlockis the substrate for every “render code professionally” surface in the library: chat assistants, fenced markdown blocks, JSON/config viewers, card-tree “code” sections, virtual terminal walkthroughs, and snippet editors. Three modes (view / edit / terminal) cover the common cases. Streaming-friendly. Language-agnostic.

Basic — view

import { CodeBlock } from "@/components/code-block";

<CodeBlock filename="app.tsx" value={code} />

Edit mode (controlled)

<CodeBlock
  mode="edit"
  lang="ts"
  filename="greet.ts"
  value={code}
  onChange={({ value }) => setCode(value)}
  onSave={({ value }) => save(value)}
/>

Streaming (chat assistant)

<CodeBlock
  lang="ts"
  value={partial}
  streaming={isStillStreaming}
/>

Terminal

<CodeBlock
  mode="terminal"
  showTrafficLights
  lines={[
    { kind: "input",  text: "$ pnpm install" },
    { kind: "output", text: "Resolving... done" },
    { kind: "error",  text: "ENOENT: no such file" },
  ]}
/>

Notes

  • Filename → lang priority: lang (if set) wins; else filenameToLang consumer override; else built-in extension map; else plaintext.
  • Streaming: explicit streaming prop. Final clean-tokenize fires when you flip it back to false. Don't auto-detect from update frequency.
  • RSC posture: the v0.1.0 client variant SSRs the first paint fine in Next.js. A dedicated zero-client-Shiki /server export defers to v0.2.0.
  • Edit ↔ view continuity: near-match in v0.1.0 (custom CodeMirror HighlightStyle approximating GitHub Light + Dark Default). Pixel-perfect Shiki bridge defers to v0.2.0.
  • Diff: use lang="diff" for unified diff text in v0.1.0; split-view will be a sibling code-diff component.
  • Long blocks: opt-in via maxLines; renders a fade-out + “Show all (N more lines)” button.

Features

  • Three render modes (view / edit / terminal) in one component, switched by `mode` prop
  • Shiki tokenization for view mode (GitHub Light + Dark Default by default; consumer overridable)
  • CodeMirror 6 in edit mode with custom HighlightStyle for near-match view/edit visual continuity
  • Streaming-friendly: explicit `streaming` prop, rAF-batched re-tokenization, blinking tail cursor
  • Terminal mode with `lines: TerminalLine[]` API (input / output / error kinds) + prompt detection + optional macOS traffic-lights
  • Chrome: filename pill, language label, copy button (with success animation), expand-to-modal, wrap toggle, download button — all gated by `show*` flags
  • Body: optional line numbers (default off in view), wrap or scroll, highlighted line ranges, severity-icon annotations with tooltips, long-block collapse with 'Show all'
  • Filename → lang priority chain: `lang` prop > consumer `filenameToLang` > built-in 30-entry extension map > plaintext
  • Dual-theme via CSS variables: `.dark` class toggles palette with zero re-tokenize
  • Standalone header parts exported (`<CodeBlockCopyButton>`, `<CodeBlockTrafficLights>`, etc.) for `renderHeader` slot composition
  • Object-shape callbacks throughout (per F-cross-12)
  • Imperative handle: `copy()`, `focus()`, `getValue()`, `scrollToLine()`

Tags

code-blocksyntax-highlightshikicodemirrorterminalchatmarkdowneditorviewerstreaming

Dependencies

shadcn primitives: button, dialog, tooltip
npm peer deps: shiki@^4.0.2, @codemirror/state@^6.6.0, @codemirror/view@^6.41.1, @codemirror/commands@^6.10.3, @codemirror/language@^6.12.3, @codemirror/autocomplete@^6.20.1, @lezer/highlight@^1.2.3, @codemirror/lang-javascript@^6.2.5, @codemirror/lang-json@^6.0.2, @codemirror/lang-python@^6.2.1, @codemirror/lang-html@^6.4.11, @codemirror/lang-css@^6.3.1, @codemirror/lang-markdown@^6.5.0, lucide-react@^1.11.0