Legacy Code Block
Shiki highlighting, line numbers, copy, and scroll area for long snippets. Not tied to Markdown.
Deprecated
This is the previous engine, kept installable for existing apps. New code uses Markdown Renderer, which renders fenced code with shadcn Code Block and Mermaid with Streamdown.
Plus Registry
This component ships from registry.plus.json, not the public registry.json. Set up @f-ui-plus and a token on the Installation page, then install @f-ui-plus/legacy-code-block below.
The legacy-code-block registry item provides LegacyCodeBlock: syntax highlighting (Shiki), optional chrome (title bar), line numbers with a sticky gutter on horizontal scroll, optional word wrap, copy, and a scrollable body for long files. Source stays visible as plain monospace until highlight is ready (plain-first); pass loading only to force a spinner for demos. Use it anywhere you need a polished code viewer; legacy-markdown-renderer can compose it for fenced blocks.
Scroll / copy layout (Chakra CodeBlock / GitHub-class): copy chrome lives outside the overflow-auto scrollport (header when chrome, absolute overlay when minimal). One scrollport owns both axes so the horizontal scrollbar stays pinned while you scroll vertically; sticky gutters pin on that same scrollport. Path titles truncate the directory and keep the basename; an optional file-type icon sits left of the label.
For rendered diagram previews (image view, zoom, pan, export), use the dedicated Legacy Mermaid Renderer component—not LegacyCodeBlock alone.
When To Use
- Standalone syntax-highlighted snippets with chrome, line numbers, copy, and scroll — not tied to Markdown.
- Prefer JSON View when the operator inspects a parsed object (payload, request/response) rather than reading a source document.
- Prefer Markdown Renderer when the host is a document; it renders fences with shadcn Code Block and Mermaid with Streamdown.
- Prefer Legacy Mermaid Renderer for interactive diagram preview (zoom/pan/export).
Installing
Configure @f-ui-plus and FUI_PLUS_REGISTRY_TOKEN as in Installation — Plus Registry.
FUI_PLUS_REGISTRY_TOKEN=xxx pnpm dlx shadcn@latest add @f-ui-plus/legacy-code-blockFUI_PLUS_REGISTRY_TOKEN=xxx npx shadcn@latest add @f-ui-plus/legacy-code-blockFUI_PLUS_REGISTRY_TOKEN=xxx yarn dlx shadcn@latest add @f-ui-plus/legacy-code-blockFUI_PLUS_REGISTRY_TOKEN=xxx bun x shadcn@latest add @f-ui-plus/legacy-code-blockregistryDependencies: copy-affordance, file-type-icon. Runtime: shiki, next-themes (for light/dark theme alignment).
Usage
import { LegacyCodeBlock } from "@/components/f-ui/legacy-code-block/legacy-code-block";
export function Example() {
return (
<LegacyCodeBlock
source={'console.log("hi")'}
language="ts"
title="example.ts"
/>
);
}Examples
Minimal (Default)
"use client";
import { LegacyCodeBlock } from "@/components/f-ui/legacy-code-block/legacy-code-block";
import { HONO_SAMPLE } from "@/demos/legacy-code-block/samples";
export function LegacyCodeBlockMinimalDemo() {
return <LegacyCodeBlock source={HONO_SAMPLE} language="ts" />;
}Chrome + Line Numbers
Long path titles truncate the directory with an ellipsis while preferring the basename; when the name alone is too long it can ellipsis too. An optional file-type icon appears left of the label when a title is set.
"use client";
import { LegacyCodeBlock } from "@/components/f-ui/legacy-code-block/legacy-code-block";
import { HONO_SAMPLE } from "@/demos/legacy-code-block/samples";
export function LegacyCodeBlockChromeLineNumbersDemo() {
return (
<LegacyCodeBlock
source={HONO_SAMPLE}
language="ts"
title="examples/powerapp/web/src/server.ts"
chrome
lineNumbers
copyStyle="always"
/>
);
}Long Lines (Sticky Gutter on Horizontal Scroll)
"use client";
import { LegacyCodeBlock } from "@/components/f-ui/legacy-code-block/legacy-code-block";
import { LONG_LINE_ROUTER_SAMPLE } from "@/demos/legacy-code-block/samples";
/** Long lines: sticky line-number gutter while code scrolls horizontally. */
export function LegacyCodeBlockStickyGutterDemo() {
return (
<LegacyCodeBlock
source={LONG_LINE_ROUTER_SAMPLE}
language="ts"
title="router.ts"
chrome
lineNumbers
copyStyle="always"
/>
);
}Word Wrap + Line Numbers
"use client";
import { LegacyCodeBlock } from "@/components/f-ui/legacy-code-block/legacy-code-block";
import { LONG_LINE_ROUTER_SAMPLE } from "@/demos/legacy-code-block/samples";
export function LegacyCodeBlockWordWrapDemo() {
return (
<LegacyCodeBlock
source={LONG_LINE_ROUTER_SAMPLE}
language="ts"
title="router.ts"
chrome
lineNumbers
wordWrap
copyStyle="always"
/>
);
}Loading (Forced Spinner)
The demo below sets loading to force the spinner (demos only). Normal usage keeps plain source visible until highlight is ready.
Pass loading to show the same spinner the component uses while Shiki initializes—no duplicate markup.
import { LegacyCodeBlock } from "@/components/f-ui/legacy-code-block/legacy-code-block"
const SOURCE = 'console.log("hello")'
/** Uses `loading` so the doc demo does not duplicate LegacyCodeBlock internals. */
export function LegacyCodeBlockLoadingDemo() {
return (
<div className="space-y-3">
<p className="text-muted-foreground text-sm">
Pass <code className="rounded bg-muted px-1 py-0.5 font-mono text-xs">loading</code> to
show the same spinner the component uses while Shiki initializes—no duplicate markup.
</p>
<LegacyCodeBlock
source={SOURCE}
language="ts"
title="example.ts"
chrome
loading
/>
</div>
)
}Mermaid (Highlighted Source)
LegacyCodeBlock with language="mermaid" behaves like any other language: Shiki highlighting, copy, scroll, and optional chrome or line numbers.
Preview vs. Source Only
This shows syntax-highlighted Mermaid text only. For an interactive diagram preview (Image/Code toggle, toolbar, fullscreen), use Legacy Mermaid Renderer.
"use client";
import { LegacyCodeBlock } from "@/components/f-ui/legacy-code-block/legacy-code-block";
import { MERMAID_SAMPLE } from "@/demos/legacy-code-block/samples";
export function LegacyCodeBlockMermaidDemo() {
return <LegacyCodeBlock source={MERMAID_SAMPLE} language="mermaid" />;
}API Reference
| Prop | Type | Description |
|---|---|---|
source | string | Raw source (copied on Copy). |
language | string | Shiki language id or alias (rust, c++, go, …). Warm-loads mainstream languages; any other Shiki bundled grammar loads on demand. Omit for plain monospace. |
title | string | Header label when chrome is on; overrides language in the header. |
showFileIcon | boolean | Chrome only. Default on when title is set; off for language-only chrome. Uses File Type Icon. |
chrome | boolean | Show title bar (default false). |
lineNumbers | boolean | Show gutter (default false). |
lineStart | number | First line number (default 1). |
wordWrap | boolean | Soft-wrap long lines (default false). |
showCopy | boolean | Show copy control (default true). |
copyStyle | "hover" | "always" | Minimal (no chrome) overlay visibility (default hover). With chrome, copy always sits in the non-scrolling header. |
maxHeightClassName | string | Tailwind class for scroll region height (default max-h-[min(70vh,28rem)]). |
className | string | Outer container. |
classNames | LegacyCodeBlockClassNames | Optional slots: root, header, titleRow, scroll, body, pre. |
loading | boolean | If true, forces a spinner and hides source (demos only). |
While Shiki (or an on-demand grammar) is warming, the block shows plain monospace source — not a spinner — then swaps to highlighted HTML once ready.