Add this component

npx zentauri-ui add json-viewer

Accessibility notes

Keyboard accessible by default with semantic markup, visible focus treatment, and tokenized states. Add descriptive labels for icon-only or decorative usage.

Dependency notes

Check Installation for shared peers. This component keeps styling in Tailwind classes and the --zui-* token contract.

Data display

JSON Viewer for inspecting structured data

Use the JSON viewer to render any JSON-serializable value as an interactive, collapsible tree. Objects and arrays expand and collapse with a disclosure toggle, primitives are syntax-colored by type (strings, numbers, booleans, null), and an optional toolbar adds expand-all, collapse-all, and copy-to-clipboard controls.

{
"ok"true,
"status"200,
"user"{
"id""u_8f21",
"name""Ada Lovelace",
"roles"[], 2 items
"verified"true,
"lastLogin"null
},
"items"[
0{}, 3 keys
1{} 3 keys
]
}

JSON viewer playground

Pick a payload, chrome appearance, and size to preview the JSON viewer live. Toggle the toolbar to expose expand-all / collapse-all / copy controls, switch on a motion preset, and use Show output / Show code to copy the matching snippet.


{
"ok"true,
"status"200,
"user"{
"id""u_8f21",
"name""Ada Lovelace",
"roles"[
0"admin",
1"editor"
],
"verified"true,
"lastLogin"null
},
"items"[
0{
"id"1,
"title""First post",
"tags"[
0"intro"
]
},
1{
"id"2,
"title""Second post",
"tags"[
0"update",
1"release"
]
}
]
}

All appearances

Every shipped chrome appearance over the same payload. Click any card to load it into the playground above.

{
"name""zentauri-ui",
"version""2.5.0",
"private"false,
"scripts"{
"dev""turbo run dev",
"build""turbo run build"
},
"engines"{
"node"">=20"
}
}
{
"name""zentauri-ui",
"version""2.5.0",
"private"false,
"scripts"{
"dev""turbo run dev",
"build""turbo run build"
},
"engines"{
"node"">=20"
}
}
{
"name""zentauri-ui",
"version""2.5.0",
"private"false,
"scripts"{
"dev""turbo run dev",
"build""turbo run build"
},
"engines"{
"node"">=20"
}
}
{
"name""zentauri-ui",
"version""2.5.0",
"private"false,
"scripts"{
"dev""turbo run dev",
"build""turbo run build"
},
"engines"{
"node"">=20"
}
}

Json Viewer API

Generated from the package prop types and variant definitions.

JsonViewer

JsonViewerProps

Variants

PropTypeDefault
appearance
contrastdefaultglasssubtle
default
size
lgmdsm
md

Behavior

PropTypeDefault
data*The JSON-serializable value to render.unknownnone
defaultExpandedDepthExpand containers whose depth is below this value. Higher values show more nested content, lower values collapse more. Defaults to expanding everything.number | undefinednone
enableClipboardShow a copy button that copies the pretty-printed JSON.boolean | undefinednone
labelsOverride default toolbar copy.JsonViewerLabels | undefinednone
quoteStringsRender quotes around string values (and stringify-escape them).boolean | undefinednone
showItemCountShow the count of keys / items next to a container's preview.boolean | undefinednone
showToolbarShow the toolbar with expand-all / collapse-all / copy controls.boolean | undefinednone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

JsonViewerVariant

JsonViewerVariantProps

Behavior

PropTypeDefault
appearance'default' | 'subtle' | 'contrast' | 'glass' | null | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone

JsonViewerAnimated

JsonViewerAnimatedProps

animated

Behavior

PropTypeDefault
animationExpand/collapse motion preset for container nodes.JsonViewerAnimation | undefinednone
appearance'default' | 'subtle' | 'contrast' | 'glass' | null | undefinednone
data*The JSON-serializable value to render.unknownnone
defaultExpandedDepthExpand containers whose depth is below this value. Higher values show more nested content, lower values collapse more. Defaults to expanding everything.number | undefinednone
enableClipboardShow a copy button that copies the pretty-printed JSON.boolean | undefinednone
labelsOverride default toolbar copy.JsonViewerLabels | undefinednone
quoteStringsRender quotes around string values (and stringify-escape them).boolean | undefinednone
refAllows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).Ref<HTMLDivElement> | undefinednone
showItemCountShow the count of keys / items next to a container's preview.boolean | undefinednone
showToolbarShow the toolbar with expand-all / collapse-all / copy controls.boolean | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone
CSS variable overrides

JSON Viewer CSS variables

Override these JSON viewer variables on :root, a theme selector, or a component wrapper.

40 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-json-viewer-border: #0000001a;
  --zui-json-viewer-bg: oklch(98.4% 0.003 247.858);
  --zui-json-viewer-fg: oklch(20.8% 0.042 265.755);
  --zui-json-viewer-subtle-bg: oklch(92.9% 0.013 255.508);
  --zui-json-viewer-contrast-bg: #ffffff;
  --zui-json-viewer-glass-bg: #ffffffcc;
  --zui-json-viewer-glass-border: #ffffff66;
  --zui-json-viewer-toolbar-bg: oklch(96.8% 0.007 247.896);
  --zui-json-viewer-toolbar-fg: oklch(44.6% 0.043 257.281);
  --zui-json-viewer-action-fg: oklch(44.6% 0.043 257.281);
  --zui-json-viewer-action-hover-bg: #0000000d;
  --zui-json-viewer-key-fg: #7c3aed;
  --zui-json-viewer-string-fg: #16a34a;
  --zui-json-viewer-number-fg: #2563eb;
  --zui-json-viewer-boolean-fg: #c2410c;
  --zui-json-viewer-null-fg: #64748b;
  --zui-json-viewer-punctuation-fg: #64748b;
  --zui-json-viewer-preview-fg: #94a3b8;
  --zui-json-viewer-toggle-fg: #64748b;
  --zui-json-viewer-guide-border: #0000000f;
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-json-viewer-border-dark: #ffffff1a;
  --zui-json-viewer-bg-dark: oklch(12.9% 0.042 264.695);
}

What it does

Use the JSON viewer to render any JSON-serializable value as an interactive, collapsible tree. Objects and arrays expand and collapse with a disclosure toggle, primitives are syntax-colored by type (strings, numbers, booleans, null), and an optional toolbar adds expand-all, collapse-all, and copy-to-clipboard controls.

Composition and API

Pass any JSON-serializable value through the data prop. The viewer walks the structure recursively, rendering objects and arrays as collapsible nodes and primitives with per-type syntax colors. defaultExpandedDepth seeds how deep the tree starts open (0 collapses everything but the root), showToolbar toggles the expand/collapse/copy controls, enableClipboard controls the copy button, showItemCount appends key/item counts to collapsed nodes, and quoteStrings controls whether string values are quoted. The separate animated entry adds collapse and fade motion presets for the expand/collapse transition.

Accessibility

Each container's disclosure control is a real button with aria-expanded reflecting its open state, so keyboard and screen-reader users can fold and unfold nodes. The root and every node carry data-slot attributes for styling and testing, and value spans expose a data-kind attribute. The rotating caret is decorative (aria-hidden), and the animated entry's motion is short and easing-based; pair it with prefers-reduced-motion handling in your app where needed.

Next.js integration notes

The static JsonViewer entry ships no framer-motion and is safe in any Server or Client Component tree (it is a Client Component because it manages expansion state). The animated JsonViewerAnimated entry imports framer-motion, which is an optional peer dependency — install it only if you use the animated entry. Both render deterministically from the same data, so server and client output match and there is no hydration mismatch.

FAQ

Can it render any JSON value, including arrays and nested objects?

Yes. Pass any JSON-serializable value to the data prop — objects, arrays, strings, numbers, booleans, or null. Containers render as collapsible nodes and primitives are colored by type. A primitive passed directly (for example a string) renders as a single colored value.

How do I control how much of the tree is expanded initially?

Use defaultExpandedDepth. Leave it unset to expand everything, set it to 1 to show only the top level expanded, or 0 to collapse everything but the root. The toolbar's Expand all / Collapse all buttons override it at runtime.

Do I need framer-motion?

Only for the animated entry. The default import from @zentauri-ui/zentauri-components/ui/json-viewer is framer-motion-free. Import JsonViewerAnimated from the /animated subpath when you want collapse or fade transitions, and install framer-motion as a peer dependency.

How do I theme the syntax colors?

Override the --zui-json-viewer-* CSS variables (key, string, number, boolean, null, punctuation, border, bg, and more) on :root, a theme selector, or a wrapper. Each variable ships a light fallback and a paired -dark variant for dark mode.