Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

JSON Text for React

JSON that writes itself out, each key typed and its value following. For React with Base UI, when an API response or a config should read as if it's being written.

Framework

JSON Text sets any value as formatted JSON and writes it out: each key is typed a character at a time, its value fades in a beat later, then the next key, through every level of nesting, once it scrolls into view. Strings, numbers, booleans and null each take their own colour.

Use it for an API response, a webhook payload or a config file on a landing page, where the data is the point. To let people explore real data, opening and closing its branches, use JSON Tree View instead; for code, Syntax Text. Keys are typed by a stepped CSS clip, values fade in with a CSS keyframe animation the install adds to your stylesheet, each timed to its moment in the writing, with no animation library. With reduced motion the JSON 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 { JsonText } from "@/components/ui/json-text";
<JsonText data={{ status: "ok", items: 3 }} />

Demos

Response

data takes anything JSON can hold, nested as deep as you like; indent is the spaces per level, 2 by default.

Preview width

Timing

speed is the time to type one character of a key, 30 ms by default, and stagger the pause after a key before its value, and after a value before the next key, 100 ms. Slow them down for a small payload you want read as it's written.

Preview width

Accessibility

The JSON is real text in a <pre> and <code>, read once by screen readers and selectable, exactly as JSON.stringify would write it; colour is decoration on top of it. It always reads left to right, even on a right-to-left page. The colours are your theme's text colours, readable in light and dark. With reduced motion the JSON is there from the start.

FAQ

Should I use this or JSON Tree View?

JSON Text is for showing: a fixed, short value that writes itself out once, on a marketing or docs page. JSON Tree View is for exploring: real data of any size, with branches people open and close from the keyboard. Both colour strings, numbers and booleans in the same hues, so the two sit well on one page.

What can I pass as data?

Anything JSON can hold: objects, arrays, strings, numbers, booleans and null, nested. It goes through JSON's own round trip first, so a Date shows as its string, and what JSON leaves out, such as functions and undefined, is left out here too.

In what order are the keys written?

In your object's order, the order JSON.stringify uses. If a formatter sorts your object's keys, the JSON shows them sorted.

How long does it take?

It grows with the data: each key takes its length times speed, plus stagger twice. A handful of keys takes two or three seconds; keep the data short, or lower speed and stagger for a bigger one.

Why is it monospaced?

JSON lines up only when every character is the same width, and the keys are typed out by a clip that opens one character width at a time. Keep font-mono.

When does it play?

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

What happens with reduced motion?

Nothing is typed or faded: the JSON is there from the start, coloured.

API Reference

JsonText

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

PropType
dataunknown

The value shown: anything JSON can hold, nested as deep as you like. What JSON leaves out (functions, undefined) is left out here too.

indent?number

Spaces per level of nesting. @default 2.

Default
2
speed?number

The time to type one character of a key, in milliseconds. @default 30.

Default
30
stagger?number

The pause after a key before its value, and after a value before the next key, in milliseconds.

Default
100
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
--json-text-durationstring

One value's fade in (300ms).

All 97 text effects