https://github.com/humanspeak/svelte-json-view-lite
Lightweight JSON tree view component for Svelte — fast, zero-dependency, collapsible, and fully customizable.
https://github.com/humanspeak/svelte-json-view-lite
a11y collapsible frontend json json-view json-viewer keyboard-navigation lightweight runes svelte svelte-component svelte-library svelte5 sveltekit syntax-highlighting tree-view typescript zero-dependencies
Last synced: 5 days ago
JSON representation
Lightweight JSON tree view component for Svelte — fast, zero-dependency, collapsible, and fully customizable.
- Host: GitHub
- URL: https://github.com/humanspeak/svelte-json-view-lite
- Owner: humanspeak
- License: mit
- Created: 2026-04-19T14:19:19.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-06-25T20:16:07.000Z (8 days ago)
- Last Synced: 2026-06-25T21:15:37.713Z (8 days ago)
- Topics: a11y, collapsible, frontend, json, json-view, json-viewer, keyboard-navigation, lightweight, runes, svelte, svelte-component, svelte-library, svelte5, sveltekit, syntax-highlighting, tree-view, typescript, zero-dependencies
- Language: TypeScript
- Homepage: https://jsonview.svelte.page
- Size: 9.78 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Notice: NOTICE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# @humanspeak/svelte-json-view-lite
Fast, tiny JSON tree viewer for Svelte 5 — a port of
[react-json-view-lite](https://github.com/AnyRoad/react-json-view-lite)
(MIT © 2024 AnyRoad) with runes, SSR, per-type snippet overrides, and zero
runtime dependencies.
[](https://www.npmjs.com/package/@humanspeak/svelte-json-view-lite)
[](https://github.com/humanspeak/svelte-json-view-lite/actions/workflows/npm-publish.yml)
[](https://coveralls.io/github/humanspeak/svelte-json-view-lite?branch=main)
[](https://github.com/humanspeak/svelte-json-view-lite/blob/main/LICENSE)
[](https://www.npmjs.com/package/@humanspeak/svelte-json-view-lite)
[](https://github.com/humanspeak/svelte-json-view-lite/actions/workflows/codeql.yml)
[](https://packagephobia.com/result?p=@humanspeak/svelte-json-view-lite)
[](https://trunk.io)
[](http://www.typescriptlang.org/)
[](https://www.npmjs.com/package/@humanspeak/svelte-json-view-lite)
[](https://github.com/humanspeak/svelte-json-view-lite/graphs/commit-activity)
## Features
- Svelte 5 runes throughout (`$props`, `$state`, `$derived`, `$effect`).
- Drop-in API parity with `react-json-view-lite`: same prop names, themes,
and strategy helpers.
- Per-type `Snippet` overrides for custom value rendering (strings, numbers,
dates, etc.) — new in the Svelte port.
- SSR-safe: uses `$props.id()` for stable `aria-controls` linkage across
server/client.
- Keyboard accessible: roving tabindex + `ArrowUp`/`ArrowDown`/`ArrowLeft`/
`ArrowRight` navigation, full WAI-ARIA treeview semantics.
- Ships built-in light and dark themes via CSS Modules.
## Installation
```bash
npm i -S @humanspeak/svelte-json-view-lite
# or
pnpm add @humanspeak/svelte-json-view-lite
```
## Basic usage
```svelte
import { JsonView, defaultStyles } from '@humanspeak/svelte-json-view-lite'
const data = {
name: 'Ada Lovelace',
tags: ['admin', 'beta'],
active: true,
joined: new Date('2024-01-15')
}
```
## Props
| Prop | Type | Default | Description |
| ----------------------- | ---------------------------------------- | --------------- | ---------------------------------------------------------------------------------- |
| `data` | `object \| unknown[]` | — | The JSON-shaped value to render. |
| `style` | `Partial` | `defaultStyles` | Classname-map that themes every slot. |
| `shouldExpandNode` | `(level, value, field?) => boolean` | `allExpanded` | Initial-expand strategy per node. |
| `clickToExpandNode` | `boolean` | `false` | When true, clicking the field label also toggles the node. |
| `beforeExpandChange` | `(event: NodeExpandingEvent) => boolean` | — | Return `false` to veto an expand/collapse transition. |
| `compactTopLevel` | `boolean` | `false` | Spread root-object entries instead of nesting them under a single root expander. |
| `string`, `number`, ... | `Snippet<[{ value, field?, level }]>` | — | Optional per-type renderer overrides. See [Snippet overrides](#snippet-overrides). |
Any additional HTML attributes (`aria-*`, `data-*`, `id`, `class`, etc.) are
forwarded onto the root `
`.
## Themes
Two themes ship out of the box:
```svelte
import { JsonView, defaultStyles, darkStyles } from '@humanspeak/svelte-json-view-lite'
```
Override individual slots by spreading:
```svelte
```
## Retheme via CSS variables
Every color in the built-in themes is declared as a CSS custom property
on the root container, so you can tweak one or more colors without
swapping the entire `style` prop or bringing your own classname map.
The variables all live under the `--sjv-*` namespace:
| Variable | Default (light) | Default (dark) | Applies to |
| ------------------- | ------------------ | -------------------- | ------------------------------------------ |
| `--sjv-background` | `#eee` | `rgb(0, 43, 54)` | Root container background |
| `--sjv-label` | `#000000` | `rgb(253, 246, 227)` | Field label text |
| `--sjv-punctuation` | `#000000` | `rgb(253, 246, 227)` | Brackets, colons, commas |
| `--sjv-string` | `rgb(42, 63, 60)` | `rgb(203, 75, 22)` | String values |
| `--sjv-number` | `#0b75f5` | `rgb(211, 54, 130)` | Number & BigInt values |
| `--sjv-boolean` | `rgb(70, 144, 56)` | `rgb(174, 129, 255)` | Boolean values |
| `--sjv-null` | `#df113a` | `rgb(129, 181, 172)` | `null` literal |
| `--sjv-undefined` | `#df113a` | `rgb(129, 181, 172)` | `undefined` literal |
| `--sjv-other` | `#43413d` | `rgb(38, 139, 210)` | Dates, functions, symbols, etc. |
| `--sjv-expander` | `#000000` | `rgb(253, 246, 227)` | `▸` / `▾` icons and collapsed `...` marker |
**Global override** — applies to every `JsonView` on the page:
```css
:root {
--sjv-string: lavender;
--sjv-number: #ff71ce;
}
```
**Scoped override** — target one component (or a subtree):
```svelte
.vaporwave :global(div[role='tree']) {
--sjv-background: #2b1055;
--sjv-string: #01cdfe;
--sjv-number: #05ffa1;
--sjv-boolean: #b967ff;
}
```
**Per-instance override** — forward inline styles via the root div (ARIA
attrs and `style` on `` are spread onto the wrapper):
```svelte
```
All three patterns work with either `defaultStyles` or `darkStyles` —
the variables are defined on both container classes with theme-specific
fallback defaults, so one override applies to whichever theme is active.
See the `/test/css-variables` playground route for a live example.
## Snippet overrides
Unlike the React lib, `svelte-json-view-lite` exposes typed `Snippet`
overrides for every primitive type plus the field label. Each snippet
receives `{ value, field?, level }`; omit the snippet to fall through to
the default rendering.
```svelte
import {
JsonView,
type DateSnippetProps,
type StringSnippetProps
} from '@humanspeak/svelte-json-view-lite'
const data = {
joined: new Date('2024-01-15'),
docs: 'https://example.com/docs'
}
function relative(d: Date): string {
const days = Math.round((d.getTime() - Date.now()) / 86_400_000)
return new Intl.RelativeTimeFormat('en').format(days, 'day')
}
{#snippet date({ value }: DateSnippetProps)}
{relative(value)}
{/snippet}
{#snippet string({ value }: StringSnippetProps)}
{#if /^https?:/.test(value)}
{value}
{:else}
"{value}"
{/if}
{/snippet}
```
Available snippets: `string`, `number`, `boolean`, `null`, `undefined`,
`bigint`, `date`, `function`, `label`. Their typed prop interfaces
(`StringSnippetProps`, `LabelSnippetProps`, etc.) are all exported from
the package root.
## Expand strategies
```svelte
import { JsonView, collapseAllNested, allExpanded } from '@humanspeak/svelte-json-view-lite'
level < 2} />
```
## Migrating from `react-json-view-lite`
The Svelte API preserves the React prop names and theme-object shape. Only
two differences exist:
| React | Svelte |
| --------------------------- | ---------------------------------------------------------- |
| `style.ariaLables` (typoed) | `style.ariaLabels` (fixed; typo still honored with a warn) |
| — (not supported) | Per-type `Snippet` overrides |
Everything else — `style`, `clickToExpandNode`, `compactTopLevel`,
`beforeExpandChange`, `shouldExpandNode`, `defaultStyles`, `darkStyles`,
`allExpanded`, `collapseAllNested` — works identically.
## Accessibility
- Root element has `role="tree"` with `aria-label="JSON view"` (overridable).
- Every expandable node is a `role="treeitem"` with live `aria-expanded`
and, when open, `aria-controls` pointing at its child `
`.
- Keyboard support follows the [WAI-ARIA 1.2 Treeview pattern]:
- `ArrowRight` expands, `ArrowLeft` collapses.
- `ArrowDown` / `ArrowUp` move focus between expanders (wrapping).
- Roving `tabindex` keeps only one expander in the tab order.
[WAI-ARIA 1.2 Treeview pattern]: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
## Development
```bash
pnpm install
pnpm dev # launch SvelteKit playground on :8233
pnpm check # svelte-check
pnpm test # vitest + coverage
pnpm build # vite build + svelte-package + publint
```
## Svelte 5 ecosystem
Part of the [Humanspeak](https://humanspeak.com) family of runes-native Svelte 5 packages:
| Package | Description |
| --- | --- |
| [@humanspeak/svelte-markdown](https://markdown.svelte.page) | Runtime markdown renderer for Svelte |
| [@humanspeak/svelte-virtual-list](https://virtuallist.svelte.page) | Virtual scrolling for Svelte |
| [@humanspeak/svelte-motion](https://motion.svelte.page) | Framer Motion for Svelte 5 |
| [@humanspeak/svelte-headless-table](https://table.svelte.page) | Headless data tables for Svelte |
| [@humanspeak/svelte-diff-match-patch](https://diff.svelte.page) | Diff comparison for Svelte |
| [@humanspeak/svelte-purify](https://purify.svelte.page) | HTML sanitisation for Svelte |
| [@humanspeak/svelte-virtual-chat](https://virtualchat.svelte.page) | Virtual chat viewport for Svelte 5 |
| [@humanspeak/memory-cache](https://memory.svelte.page) | In-memory cache for TypeScript |
| **[@humanspeak/svelte-json-view-lite](https://jsonview.svelte.page)** — _this package_ | JSON tree viewer for Svelte 5 |
| [@humanspeak/svelte-scoped-props](https://scoped.svelte.page) | Scoped class props for Svelte |
## License
MIT © [Humanspeak, Inc.](LICENSE)
## Credits
Made with ❤️ by [Humanspeak](https://humanspeak.com)