shadcn.io is not affiliated with official shadcn/ui
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.
Installation
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.
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.
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.
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.
API Reference
SyntaxText
<div> data-slot="syntax-text"
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.
data-kind?string
Mirrors kind.
data-view?string
"in" when visible is true, otherwise "out".
--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).
Related
- Pro
Diff Text
EntranceShow a change between two versions
- Pro
JSON Text
EntranceA data object written key by key
- Pro
Terminal Text
EntranceA command typed and run
- Pro
Regex Text
DecorativeMatches of a pattern, walked in turn
- Pro
Log Stream Text
MotionLog lines that keep arriving
- Pro
Copy Text
InteractivePress the text to copy it