JSON view

Shows structured output as a foldable tree the person can search and copy from.

Examples

A tool result with search and path

{
"tool": "issue_refund",
"ok": true,
"input": {
"order": "ord_4812",
"amount": 42.5,
"currency": "usd",
"reason": "Item arrived damaged"
"output": {
"refund": "re_demo_91c0",
"status": "succeeded",
"note": "The customer wrote on Oct 11 that the box arrived crushed and the lamp inside w…
"warnings": [],
"trace": null
Path$

A small payload, no toolbar

{
"run": "run_01J9ZKQX8M2V4E7Q",
"agent": "support-agent",
"status": "ok",
"tokens": 2418,

Closed to the first level

{
"tool": "issue_refund",
"ok": true,
"warnings": [],
"trace": null
Path$

Chrome

  • {
    "run": "run_01J9ZKQX8M2V4E7Q",
    "agent": "support-agent",
    "status": "ok",
    "tokens": 2418,
    "tags": [
    0: "refund",
    1: "eval"
    Path$

    fulldefault

  • {
    "run": "run_01J9ZKQX8M2V4E7Q",
    "agent": "support-agent",
    "status": "ok",
    "tokens": 2418,
    "tags": [
    0: "refund",
    1: "eval"

    plain

States

  • {
    "run": "run_01J9ZKQX8M2V4E7Q",
    "agent": "support-agent",
    "status": "ok",
    "tokens": 2418,
    "tags": [
    0: "refund",
    1: "eval"

    open

  • closed

Usage

When to use it
Use
A tool result, a run payload or a trace span carries nested data the person inspects.
Use
The person needs the path to a value for code, a jq filter or a bug report.
Not for
The data is a flat list of fields with labels. Use Data list.
Not for
The data is code or config the person reads as text. Use Code block.
Not for
The data is many rows of the same shape. Use Table.

Rules

7 rules
Must
Pass the parsed value in data; never a JSON string. Because a string renders as one long string leaf, so nothing folds and nothing is searchable by key.
Must
Pass label as a noun phrase that names the payload: "issue_refund result". Because it names the tree and the search field for a screen reader, and the default "JSON" says nothing about which payload this is.
Never
Pass a payload that holds a live secret, a token or a full key. Because the view renders every value as text, including in search and in the copy button, and shows no mask.
Should
Set defaultExpandDepth to the level that fits the first screen; 0 starts closed. Because a fully open 500-key payload buries the part the person came for, and a closed one hides it.
Should
Turn toolbar off for a payload under about 10 rows. Because a search field over ten lines costs 40px and finds nothing the eye misses.
Should
Set maxHeight when the view sits in a page with other content; the tree scrolls inside. Because the default 420px keeps one payload from pushing the rest of a detail page off screen.
Should
Pass refs for the resource IDs in the payload so they take their kind color. Because IDs found by default are underlined in their kind hue, and refs adds the ones whose shape the default does not know.

Accessibility

5 checks
The tree follows the WAI-ARIA tree pattern: one tab stop, role="tree" with treeitems, aria-level and aria-expanded.
The search field is named "Search <label>", announces "2 of 7" or "No matches" politely, and has a clear button.
A body wider than its box becomes its own tab stop so keyboard users can scroll it.
The current match gets a pressed fill and, in forced colors, an outline.
Icon buttons are named (Open all, Close all, Copy JSON); focus shows a 2px ink outline.

Keyboard

6 keys
ArrowDown, ArrowUp
Moves to the next or previous visible row.
ArrowRight
Opens a closed branch; on an open one, moves to its first child.
ArrowLeft
Closes an open branch; otherwise moves to the parent.
Home, End
Moves to the first or last visible row.
Enter, Space
Toggles a branch, or unfolds a long string.
Enter in search
Steps to the next match; Shift+Enter goes back, Escape clears.

Edge cases

9 edge cases
String over 120 characters
Folds to its first 80 with a "+n chars" button.
Closed branch
Says how much it hides: "3 keys" or "5 items".
Searching
Opens the branches that hold a match and hides the rest; Open all and Close all are disabled.
No match
Says "Nothing matches" with the query in a code tag.
Key with a space or slash
The footer path uses bracket form: $["user agent"].
Empty object or array
Renders {} or [] on one row with no caret.
Right to left page
The tree stays left to right, as code does.
Forced colors
The current match keeps an outline, since its fill is lost.
Zoom 200%
Rows stay 24px tall; long lines scroll sideways inside the body.

API

8 props
data
unknown default required
label
string default 'JSON'
defaultExpandDepth
number default 2
toolbar
boolean default true
copy
boolean default true
path
boolean default toolbar
maxHeight
number default 420
refs
CodeRef[]

Tokens

13 tokens
--code-text
var(--ink)
--code-string
oklch(var(--ink-c) / var(--code-string-alpha))
--code-comment
oklch(var(--ink-c) / var(--code-comment-alpha))
--surface-page
var(--paper)
--surface-hover
oklch(var(--ink-c) / 0.05)
--surface-pressed
oklch(var(--ink-c) / 0.08)
--line-frame
oklch(var(--ink-c) / var(--line-frame-alpha))
--line-row
oklch(var(--ink-c) / 0.08)
--row-sm
32px
--type-code
400 13px/20px var(--font-mono)
--type-tag
var(--type-code-sm)
--dur-fast
120ms
--ease-step
cubic-bezier(0.2, 0, 0, 1)

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.