A little polish goes a long way. Rounded rows, vivid values, hover borders, and click-to-copy feedback that makes structured data feel at home in your app.
Inspired by the rounded rows in svelte-tree-view’s Tailwind example. This version uses JsonView with its public style map, Tailwind utilities,
and scoped CSS for the nested rows. Expanded objects and arrays have a filled boundary around
their children to keep each group together visually.
Copy the demo into a Svelte 5 project with Tailwind CSS configured and @humanspeak/svelte-motion and @lucide/svelte installed. Keep the utility
class names as complete strings so Tailwind can detect them. The palette is local to this viewer
and does not change your site theme.
Svelte Motion adds a spring-driven palette
indicator, a gentle entrance and button feedback. The viewer’s row, expander, collapsed, and childGroup snippets let MotionDiv, MotionSpan, and MotionUl animate the tree
directly. AnimatePresence owns the live child group during exit and reversal. The
viewer keeps control of expansion, keyboard navigation, and focus. Turn off Motion for a still
preview. Your system’s reduced-motion preference disables animations automatically.
Child rows slide vertically without scaling. Hover a caret or focus it with the keyboard to
see it lean toward its next state. The ellipsis fades with expansion, and hovering a row
nudges it and its subtree two pixels to the right. Rapid toggles reverse the slide smoothly.
For styling alone, see the Tailwind-only example. Hover a
row to highlight its border, then click its label or value to copy. Strings copy as plain
text; containers copy complete, formatted JSON, even when collapsed. A successful copy
flashes a green border and a spring-animated checkmark for two seconds. If copying fails, a
red border and cross invite a retry. Selecting text leaves your clipboard alone. Tab to a
row and press Enter or Space to copy, or use its chevron to expand and the arrow keys to
navigate. Palette and spacing changes preserve your expanded nodes. Long values wrap; arrays
and objects retain their brackets. clickToExpandSummary={false} lets
row clicks copy using a normal bubbling handler while chevrons expand. style.hideCommas removes separators from the bordered rows. The viewer contains collapsed-snippet whitespace, and
inline-flex punctuation keeps the animated ellipsis and brackets together. The caret uses focusVisible for keyboard-only tilt, so mouse focus does not leave it tilted. The
source below is the running example.