Tinyrack

Code Block

Block-level source display with optional syntax highlighting and explicit wrapping.

Contract

AxisValuesDefault
languageany grammar the configured highlighter supportsplain text
Highlighterhighlighter prop, TRCodeHighlighterProvider, nonenone
Syntax themechosen by the highlighter; the Tinyrack docs highlighter follows the active Tinyrack themegithub-light-high-contrast, github-dark-high-contrast
wraptrue, falsefalse

Install

pnpm add @tinyrack/ui

Scroll inside the code area to read long lines.

Styles

@import '@tinyrack/ui/components/code-block.css';

Scroll inside the code area to read long lines.

Imports

import { TRCodeBlock } from '@tinyrack/ui/components/code-block';

Scroll inside the code area to read long lines.

Playground

Usage

The highlighted examples use trShikiWebHighlighter. Add Shiki before copying them:

pnpm add shiki

Examples

Additional languages permalink

Use the language identifier that matches the source. An identifier the highlighter does not support renders as plain text rather than failing.

Copy action with visible result permalink

Copy is an application action, so compose it with TRButton and a live result instead of hiding clipboard state inside TRCodeBlock.

The composed copy example additionally needs these application-action imports:

import { useState } from 'react';
import { TRButton } from '@tinyrack/ui/components/button';
import '@tinyrack/ui/components/button.css';

API

TRCodeBlock ships no grammars. Supply a highlighter through the highlighter prop or TRCodeHighlighterProvider, and the set of valid language values follows from that choice. See Syntax highlighting for the setup paths.

Highlighting happens after hydration; the original source remains SSR-safe and visible until the highlighter resolves. Changing code or language cancels stale work so an earlier async result can never replace the current source.

PropTypeDefaultDescription
codestringrequiredSource text rendered inside semantic <pre><code> markup.
languagestringundefinedGrammar identifier passed to the highlighter; omit it for plain text.
highlighterTRCodeHighlighterprovider valueOverrides the highlighter from context for this block.
onHighlightFailure(failure: TRCodeHighlightFailure) => voidprovider valueReceives unsupported-language, highlight-failed, and no-highlighter outcomes.
wrapbooleanfalseWraps long lines instead of exposing horizontal overflow.
refRef<HTMLPreElement>References the native pre element.
className, stylenative pre propsApplies consumer classes, inline styles, and component-token overrides.

The block reports its state on data-highlight: plain without a language, pending while the highlighter runs, highlighted on success, unsupported when the highlighter has no grammar, no-highlighter when none is configured, and error when the highlighter throws. Every outcome other than success keeps the SSR fallback visible, so failures degrade to readable plain text rather than an empty block. Without an onHighlightFailure handler, only error reaches the console, once per language. A missing highlighter and an unsupported language are configuration states whose correct rendering is plain text, so they stay quiet and surface through data-highlight alone.

All other native pre attributes and events are forwarded. Add an aria-label when surrounding prose does not already identify the source. Highlighting never changes the accessible source text.

Styles

TokenPurpose
--tr-code-block-backgroundSurface, including highlighted blocks
--tr-code-block-borderBorder color
--tr-code-block-border-widthBorder width
--tr-code-block-colorFallback source color
--tr-code-block-font-familyMonospace family
--tr-code-block-font-sizeSource size
--tr-code-block-line-heightSource leading
--tr-code-block-padding-xInline padding
--tr-code-block-padding-yBlock padding
--tr-code-block-radiusCorner radius

With wrap={false}, the block contains long lines with horizontal overflow. With wrap, long tokens break inside the available width. Both modes stay bounded by their parent.