Skip to content

Commit 914ab5f

Browse files
committed
docs: improve json-render docs
1 parent c68c7f8 commit 914ab5f

File tree

4 files changed

+652
-146
lines changed

4 files changed

+652
-146
lines changed

docs/.vitepress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export default extendConfig(withMermaid(defineConfig({
6969
{ text: 'RPC', link: '/kit/rpc' },
7070
{ text: 'Shared State', link: '/kit/shared-state' },
7171
{ text: 'Logs', link: '/kit/logs' },
72+
{ text: 'JSON Render', link: '/kit/json-render' },
7273
{ text: 'Examples', link: '/kit/examples' },
7374
],
7475
},

docs/kit/dock-system.md

Lines changed: 26 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,8 @@ interface DockEntry {
8787
buttonStart?: string
8888
buttonLoading?: string
8989
}
90-
/** Inline JSON spec (for type: 'json-render') */
91-
spec?: JsonRenderSpec
92-
/** Shared state key holding the JSON spec (for type: 'json-render') */
93-
sharedStateKey?: string
90+
/** JsonRenderer handle created by ctx.createJsonRenderer() (for type: 'json-render') */
91+
ui?: JsonRenderer
9492
}
9593
```
9694

@@ -303,160 +301,45 @@ ctx.docks.register({
303301
304302
## JSON Render Panels
305303

306-
JSON render panels let you describe your UI as a JSON spec on the server side. The DevTools client renders it with built-in components powered by [json-render](https://github.com/vercel-labs/json-render). **No client code needed.**
304+
JSON render panels let you describe your UI as a JSON spec on the server side**no client code needed.** This is the simplest way to add a DevTools panel.
307305

308-
This is the simplest way to add a DevTools panel — you only write server-side TypeScript.
309-
310-
### Basic Example
306+
Use `ctx.createJsonRenderer()` to create a renderer handle, then pass it as `ui` when registering a `json-render` dock entry:
311307

312308
```ts
313-
import { defineJsonRenderSpec } from '@vitejs/devtools-kit'
314-
315-
ctx.docks.register({
316-
id: 'my-panel',
317-
title: 'My Panel',
318-
icon: 'ph:chart-bar-duotone',
319-
type: 'json-render',
320-
spec: defineJsonRenderSpec({
321-
root: 'root',
322-
elements: {
323-
root: {
324-
type: 'Stack',
325-
props: { direction: 'vertical', gap: 12 },
326-
children: ['heading', 'info'],
327-
},
328-
heading: {
329-
type: 'Text',
330-
props: { content: 'Hello from JSON!', variant: 'heading' },
331-
},
332-
info: {
333-
type: 'KeyValueTable',
334-
props: {
335-
entries: [
336-
{ key: 'Version', value: '1.0.0' },
337-
{ key: 'Status', value: 'Running' },
338-
],
339-
},
309+
const ui = ctx.createJsonRenderer({
310+
root: 'root',
311+
elements: {
312+
root: {
313+
type: 'Stack',
314+
props: { direction: 'vertical', gap: 12 },
315+
children: ['heading', 'info'],
316+
},
317+
heading: {
318+
type: 'Text',
319+
props: { content: 'Hello from JSON!', variant: 'heading' },
320+
},
321+
info: {
322+
type: 'KeyValueTable',
323+
props: {
324+
entries: [
325+
{ key: 'Version', value: '1.0.0' },
326+
{ key: 'Status', value: 'Running' },
327+
],
340328
},
341329
},
342-
}),
330+
},
343331
})
344-
```
345-
346-
### Dynamic Data with Shared State
347-
348-
For dynamic UIs that update over time, store the spec in a [shared state](./shared-state) key:
349332

350-
```ts
351333
ctx.docks.register({
352334
id: 'my-panel',
353335
title: 'My Panel',
354336
icon: 'ph:chart-bar-duotone',
355337
type: 'json-render',
356-
sharedStateKey: 'my-plugin:ui',
357-
})
358-
359-
const ui = await ctx.rpc.sharedState.get('my-plugin:ui', {
360-
initialValue: defineJsonRenderSpec({ /* spec */ }),
361-
})
362-
363-
// Later, update the UI reactively:
364-
ui.mutate((draft) => {
365-
draft.elements.heading.props.content = 'Updated!'
366-
})
367-
```
368-
369-
### Handling Actions via RPC
370-
371-
Buttons in the spec can trigger RPC functions on the server:
372-
373-
```ts
374-
// In the spec:
375-
defineJsonRenderSpec({
376-
// ...
377-
elements: {
378-
'refresh-btn': {
379-
type: 'Button',
380-
props: { label: 'Refresh' },
381-
on: { press: { action: 'my-plugin:refresh' } },
382-
},
383-
},
338+
ui,
384339
})
385340
```
386341

387-
```ts
388-
// On the server:
389-
ctx.rpc.register(defineRpcFunction({
390-
name: 'my-plugin:refresh',
391-
type: 'event',
392-
setup: ctx => ({
393-
handler: async () => {
394-
// Fetch new data, then update the spec
395-
ui.mutate((draft) => { /* ... */ })
396-
},
397-
}),
398-
}))
399-
```
400-
401-
### Text Input with Two-Way Binding
402-
403-
Use `$bindState` for two-way binding on text inputs, and `$state` to read the bound value in action params:
404-
405-
```ts
406-
defineJsonRenderSpec({
407-
// ...
408-
elements: {
409-
'my-input': {
410-
type: 'TextInput',
411-
props: {
412-
placeholder: 'Type here...',
413-
value: { $bindState: '/inputValue' },
414-
},
415-
},
416-
'submit-btn': {
417-
type: 'Button',
418-
props: { label: 'Submit' },
419-
on: {
420-
press: {
421-
action: 'my-plugin:submit',
422-
params: { text: { $state: '/inputValue' } },
423-
},
424-
},
425-
},
426-
}
427-
})
428-
```
429-
430-
The initial state can be set in the spec:
431-
432-
```ts
433-
defineJsonRenderSpec({
434-
root: 'root',
435-
state: { inputValue: '' },
436-
elements: { /* ... */ },
437-
})
438-
```
439-
440-
### Available Components
441-
442-
| Component | Description |
443-
|-----------|-------------|
444-
| `Stack` | Flex layout container (vertical/horizontal) |
445-
| `Card` | Container with optional title, collapsible |
446-
| `Text` | Text display (heading, body, caption, code variants) |
447-
| `Badge` | Status label (info, success, warning, error) |
448-
| `Button` | Clickable button — emits `press` event for actions |
449-
| `Icon` | Iconify icon by name |
450-
| `Divider` | Visual separator with optional label |
451-
| `TextInput` | Text input with `$bindState` two-way binding |
452-
| `KeyValueTable` | Key-value pairs display |
453-
| `DataTable` | Tabular data with columns and rows |
454-
| `CodeBlock` | Code display with optional filename |
455-
| `Progress` | Progress bar with label |
456-
| `Tree` | Expandable tree view for nested objects |
457-
458-
> [!TIP]
459-
> See the [Git UI example](/kit/examples#git-ui) for a complete interactive plugin using json-render with RPC actions, text input, and dynamic state.
342+
See the [JSON Render](/kit/json-render) page for the full component reference, dynamic updates, actions, state bindings, and examples.
460343

461344
## Communication with Server
462345

0 commit comments

Comments
 (0)