Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Syntax Text for React

A code snippet that comes in token by token, coloured like an editor. For React with Base UI, when a short code sample on a landing page should feel alive.

Framework

Syntax Text sets a snippet of code the way an editor would, with keywords, strings, numbers, comments and names (calls, tags, components) in their own colours, and brings it in token by token: each one fades and rises into place a moment after the one before, from the first line to the last, once the snippet scrolls into view.

Use it for a short sample on a landing page or a feature section: an install line, an API call, a few lines of config. For a change between two versions, use Diff Text; for a data object written out, JSON Text; for documentation, where readers copy long blocks, your site's own syntax highlighter. A small built-in tokenizer does the colouring, with no highlighter package, and each token runs a CSS keyframe animation the install adds to your stylesheet, delayed by its place in the code. With reduced motion the code is simply there.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { SyntaxText } from "@/components/ui/syntax-text";
<SyntaxText text={'const answer = await ask("What is six times seven?");'} />

Demos

Keywords

The tokenizer knows the comments, strings and numbers of most C-like languages; keywords is the list of words coloured as keywords, JavaScript and TypeScript's by default. Pass another language's, such as Python's.

Preview width

Line Numbers

lineNumbers puts each line's number in a gutter, for a code window in a hero or a feature section. The numbers are drawn by CSS, so selecting and copying the code leaves them out, and screen readers don't read them. label names the snippet, here by its file name.

Preview width

Timing

stagger is the time between one token and the next, 30 ms by default, and duration how long one takes to fade in, 400 ms. A long snippet speeds up on its own, so the whole never takes more than two seconds.

Preview width

Accessibility

The code is real text in a <pre> and <code>, read once by screen readers and selectable, exactly as written; colour is decoration on top of it. Line numbers are generated content with empty alternative text, so they're neither read nor copied. It always reads left to right, even on a right-to-left page, as code does.

The <pre> takes focus, with a ring around the snippet, so a keyboard can scroll a line wider than the box with the arrow keys. Pass label (a file name, say) to name it: it becomes a region of that name. The colours are your theme's text colours, readable in light and dark. With reduced motion the code is there from the start.

FAQ

Which languages does it colour?

Any language whose comments are // or /* */ and whose strings are quoted: JavaScript, TypeScript, JSON, CSS, Go, Rust, Java, C and their kin. Pass keywords for anything but JavaScript and TypeScript. Comments that start with #, as in Python, aren't recognised as comments.

Why not a full syntax highlighter?

A highlighter understands every language perfectly and weighs as much. Syntax Text is for a few lines on a marketing page, where a small tokenizer gives the right look in a component you can read in a minute. For documentation, use a highlighter.

Where do the colours come from?

Your theme: keywords use --warning-foreground, strings --success-foreground, numbers --info-foreground, comments and punctuation --muted-foreground, which the install adds to your theme if it doesn't have them. Calls, tags and PascalCase names use --syntax-text-function, violet, which the install adds too. Every token has a data-kind (function for names), so you can restyle one kind from your CSS.

Can I use it for a long snippet?

Yes. However long it is, it comes in within two seconds; lines that don't fit scroll sideways, as in an editor. It reads best at one to fifteen lines.

Can it show line numbers?

Yes: pass lineNumbers. Each line gets its number in a muted, right-aligned gutter, drawn with a CSS counter, so copying the code never copies the numbers and screen readers skip them. Pass label too, such as the file name, so the snippet has a name when it takes focus.

When does it play?

Once, when a quarter of the snippet is in view. Pass trigger="mount" to play it as soon as the page shows it. A page without JavaScript shows the code at once.

What happens with reduced motion?

The tokens don't fade or rise: the code is there from the start, coloured.

API Reference

SyntaxText

<div> data-slot="syntax-text"

PropType
textstring

The code. Its lines and indentation are kept.

duration?number

How long one token takes to fade in, in milliseconds. @default 400.

keywords?string[]

The words coloured as keywords, for another language than JavaScript or TypeScript.

Default
JavaScript and TypeScript's keywords
label?string

What screen readers call the code, such as its file name. The code takes focus, so a keyboard can scroll a line wider than the box; with a label it's a named region.

lineNumbers?boolean

Whether each line shows its number in a gutter. The numbers are neither selected nor copied with the code, nor read out.

Default
false
stagger?number

The time between one token and the next, in milliseconds. A long snippet goes faster, so it never takes more than two seconds in all.

Default
30
trigger?"mount" | "view"

When it plays: as soon as it's on the page, or once it scrolls into view.

Type
"mount" | "view"
Default
"view"
render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

AttributeType
data-kind?string

Mirrors kind.

data-view?string

"in" when visible is true, otherwise "out".

CSS variableType
--syntax-text-digitsstring
--syntax-text-durationstring

One token's fade in (400ms).

--syntax-text-functionstring

The colour of calls, tags and PascalCase names (the install adds it to your theme).

All 97 text effects