Shadcn Code Block: Highlight, Streaming, Diffs, AI Chat and more
Browse 27 production-ready shadcn code block components for streaming agent responses, AI chat with markdown code fences, diff review, focus walkthroughs, line selection, gutter actions, terminal output, and multi-file patches: a custom ReUI component built on Shiki and composable with Card, Frame, Tabs, and Badge.
Shadcn Code Block: Streaming, Diffs, and AI Chat
ReUI Code Block is a custom shadcn component, not part of the base shadcn/ui library, for rendering source code with syntax highlighting from Shiki. It handles the cases an AI product actually needs: code streaming in token by token, agent-proposed diffs, diagnostics on specific lines, and per-line actions, alongside the ordinary documentation cases.
Eighteen components cover the range: a streaming agent response with a caret and stick-to-bottom scrolling, an AI chat message that renders markdown code fences as they arrive, diff review with added and removed lines, focus walkthroughs, line selection for asking an assistant about a range, terminal output with no highlighting, and multi-file patches in tabs.
The component is composable rather than configured. The root renders the code surface and children supply the chrome, so the same block works bare, inside a shadcn Card, or inside a ReUI Frame without a doubled border.
What is Shadcn Code Block?
ReUI Code Block renders source code as real React elements rather than as an HTML string. Shiki tokenizes the code and the result is normalized into a plain array of lines, which is what makes per-line interaction possible: hover actions in the gutter, click and shift-click line selection, diff markers, and diagnostic backgrounds all attach to elements instead of being baked into markup.
The happy path is one tag. Pass code and a language and you get a complete block with syntax highlighting in both light and dark themes. Everything else, the header, the filename, the language label, the copy button, the wrap toggle and the expand control, is composed as children.
Streaming code and AI chat
When code arrives from a model it grows one chunk at a time. The component re-tokenizes against a deferred value and the highlighter returns the same line objects for lines that did not change, so appending a token re-renders one line rather than the whole file. Lines the highlighter has not caught up to render as plain text, so the newest token is on screen immediately and gains color a frame later.
Most chat UIs hold a markdown message rather than a raw code string. Two helpers cover that: markdownFences splits a message into prose and fenced code and reports a fence whose closing delimiter has not streamed in yet, and markdownCodeProps reads the language and source out of the props react-markdown gives a pre element. An unknown language and a half-finished fence both render as plain text instead of throwing.
Server rendering and bundle cost
The Shiki engine lives in its own module with no client directive, so a React Server Component can call highlightCode and pass the resulting lines down as plain JSON. The browser then never downloads a grammar. The same shape works without React Server Components: return lines from a Remix or TanStack Start loader and pass them to the component.
Highlighting uses Shiki's JavaScript regex engine rather than the WebAssembly one, so installing the component does not force wasm-unsafe-eval into your Content Security Policy. Shiki loads on first highlight and never on import, each language is its own chunk resolved through a static map, and passing pre-highlighted lines or turning highlighting off requests none of it.
Diffs, highlights, and focus
Line state can come from props or from Shiki notation comments. Highlighted lines, highlighted words, added and removed diff lines, focused lines and error, warning or info levels all accept either an array of line numbers or a range string such as 2-4,7. The transformers prop is passed straight to Shiki, so the notation comments from @shikijs/transformers produce the same state without a second code path.
Every piece of state is published as a data attribute on the line, which means restyling any of it is a plain CSS selector and never needs an important flag. Line numbers and diff glyphs are generated content, so they stay out of text selection: selecting code and pasting it gives exact source with no gutter digits.