tm-json-viewer-lite
v0.1.0
Published
A lightweight, themeable, accessible React component for viewing and exploring JSON data as an expandable tree.
Maintainers
Readme
tm-json-viewer-lite
A lightweight, dependency-free React component for viewing JSON data as an expandable, searchable, syntax-highlighted tree. Ships as ESM + CommonJS with TypeScript declarations, and injects its own styles at runtime — no CSS import or bundler config required.
Rename the package (in
package.json) before publishing to npm if you need a unique name.
Features
- Expandable/collapsible tree for objects, arrays, strings, numbers, booleans, and
null - "Expand All" / "Collapse All" toolbar actions
- Search box with match count and inline highlighting (auto-expands ancestors of a match)
- Copy-to-clipboard on every value (and the whole document), with a "copied" confirmation
- Light/dark theme, plus CSS variables for full customization
- Graceful handling of empty objects/arrays, circular references, and invalid input
- Keyboard-accessible controls with ARIA labels
Installation
npm install tm-json-viewer-litereact and react-dom (>=17) are peer dependencies and must already be installed in your app.
Usage
import { JsonViewer } from 'tm-json-viewer-lite';
const data = {
id: 1,
name: 'Ada Lovelace',
active: true,
tags: ['mathematician', 'writer'],
address: { city: 'London', country: 'UK' },
notes: null,
};
export function Example() {
return <JsonViewer data={data} />;
}Dark theme
<JsonViewer data={data} theme="dark" />Start fully expanded, hide search
<JsonViewer data={data} expandAll showSearch={false} />Control the default expand depth
{
/* Only the root node starts open; everything below it starts collapsed. */
}
<JsonViewer data={data} defaultExpandDepth={1} />;Props
| Prop | Type | Default | Description |
| -------------------- | ------------------- | --------- | ------------------------------------------------------------------------- |
| data | unknown | — | The value to render. Objects, arrays, strings, numbers, booleans, null. |
| defaultExpandDepth | number | 1 | Depth up to which nodes start expanded (0 = only the root). |
| expandAll | boolean | false | Start every node expanded, overriding defaultExpandDepth. |
| showCopyButton | boolean | true | Show copy-to-clipboard controls on values and the toolbar. |
| showSearch | boolean | true | Show the search box in the toolbar. |
| theme | 'light' \| 'dark' | 'light' | Visual theme. |
| className | string | — | Extra class name applied to the root element. |
| id | string | — | id applied to the root element. |
Copy-to-clipboard behavior
- Hover (or focus) a row to reveal its copy icon.
- Strings copy their raw text, without the surrounding quotes shown in the tree.
- Numbers, booleans, and
nullcopy their textual form ("42","true","null"). - Objects and arrays copy their complete value as formatted (
JSON.stringify(value, null, 2)) JSON. - The toolbar's copy button copies the entire document the same way.
- After a successful copy, the icon becomes a checkmark for ~1.5s, then reverts automatically.
- Falls back to a hidden-textarea +
document.execCommand('copy')if the async Clipboard API is unavailable (e.g. non-secure contexts, older browsers) or its permission is denied.
Search
Type in the search box to match against keys, array indexes, or leaf values (case-insensitive substring match). Matches are highlighted inline, ancestors of a match are auto-expanded, and the toolbar shows a live match count.
Customizing the theme
theme="light" / theme="dark" switch a set of CSS custom properties scoped to the component's
root element. To customize colors further, override the variables yourself via className:
.my-viewer {
--jv-key: #7c3aed;
--jv-string: #059669;
--jv-bg: #fafafa;
}<JsonViewer data={data} className="my-viewer" />See src/styles.ts for the full list of variables.
Accessibility
- Expand/collapse controls are real
<button>elements witharia-expandedand descriptivearia-labels, operable with Tab and Enter/Space. - The tree root has
role="tree"; each row is a semantic list item. - Copy buttons remain visible and reachable when focused via keyboard, even though they're hidden until hover on a pointer device.
- The search input has an associated (visually hidden)
<label>and a live match-count region.
Handling invalid or unusual data
data={undefined}renders a "No data to display" message.- A value of an unsupported type (e.g. a
Symbolor a bare function passed as the root) renders an inline error message instead of throwing. - Circular references are detected and rendered as
[Circular Reference]instead of recursing forever.
Development
npm install
npm run dev # demo app at http://localhost:5173
npm run lint
npm test
npm run build # builds dist/ (ESM + CJS + .d.ts)
npm run build:demoLicense
MIT
