A modern, sleek Vue 3 component for viewing, editing, and manipulating JSON data with two view modes: Tree Mode and Text Mode.]
- π³ Tree Mode: Hierarchical display with expandable/collapsible nodes
- π Text Mode: Raw JSON text display with syntax highlighting
- βοΈ Inline Editing: Edit values directly in the tree view
- π Key Editing: Rename object keys by double-clicking on them
- β Add/Remove Nodes: Add new key-value pairs or remove existing ones
- π Search & Filter: Search across all JSON keys and values
- π Copy to Clipboard: Easy copying of JSON content with visual feedback
- πΎ Download JSON: Save current JSON to file
- π¨ Dark/Light Theme: Support for both themes with dynamic icons
- π± Responsive Design: Works on desktop and mobile devices
- β¨οΈ Keyboard Navigation: Full keyboard support
- βΏ Accessibility: Screen reader support with proper ARIA labels
- π― Icon-Only Mode: Option to hide button text labels for compact interface
- ποΈ Customizable UI: Hide specific buttons, sections, or entire header/footer
- π Dual Build System: Library build for npm + Demo build for preview
This component is now available on npm as @ctechhindi/vue3-json-viewer
npm install @ctechhindi/vue3-json-viewer
Or with yarn:
yarn add @ctechhindi/vue3-json-viewer
Important: You need to import the CSS file to see the styles. Choose one of these options:
// Option 1: Direct CSS import (recommended) import "@ctechhindi/vue3-json-viewer/dist/index.css"; // Option 2: Using the styles export import "@ctechhindi/vue3-json-viewer/styles"; // Option 3: Using the css export import "@ctechhindi/vue3-json-viewer/css"; // Option 4: In your main.ts or main.js import "@ctechhindi/vue3-json-viewer/dist/index.css";
<template> <div> <JsonViewer v-model:data="jsonData" :editable="true" theme="light" default-mode="tree" @update:data="handleDataUpdate" /> </div> </template> <script setup lang="ts"> import { ref } from "vue"; import JsonViewer from "@ctechhindi/vue3-json-viewer"; const jsonData = ref({ name: "John Doe", age: 30, active: true, hobbies: ["reading", "coding"], address: { street: "123 Main St", city: "Anytown", }, }); const handleDataUpdate = (newData: any) => { console.log("Data updated:", newData); }; </script>
<template> <JsonViewer v-model:data="complexData" :editable="true" :theme="currentTheme" default-mode="tree" :show-line-numbers="true" :max-depth="3" :hide-action-text="false" @update:data="handleDataUpdate" @node-click="handleNodeClick" @node-expand="handleNodeExpand" @node-collapse="handleNodeCollapse" @edit-start="handleEditStart" @edit-save="handleEditSave" @edit-cancel="handleEditCancel" /> </template> <script setup lang="ts"> import { ref } from "vue"; import JsonViewer from "@ctechhindi/vue3-json-viewer"; const complexData = ref({ // Your complex JSON data }); const currentTheme = ref<"light" | "dark">("light"); // Event handlers const handleDataUpdate = (newData: any) => { console.log("Data updated:", newData); }; const handleNodeClick = (node: any) => { console.log("Node clicked:", node); }; const handleNodeExpand = (node: any) => { console.log("Node expanded:", node); }; const handleNodeCollapse = (node: any) => { console.log("Node collapsed:", node); }; const handleEditStart = () => { console.log("Edit mode started"); }; const handleEditSave = (data: any) => { console.log("Changes saved:", data); }; const handleEditCancel = () => { console.log("Edit cancelled"); }; </script>
You can hide specific UI elements using the visibility props:
<template> <JsonViewer v-model:data="jsonData" :hide-header="false" :hide-footer="true" :hide-mode-switcher="false" :hide-tree-controls="false" :hide-edit-controls="false" :hide-search-button="true" :hide-copy-button="false" :hide-download-button="true" :hide-theme-button="false" /> </template>
For a minimal, read-only viewer:
<template> <JsonViewer v-model:data="jsonData" :editable="false" :hide-header="false" :hide-footer="true" :hide-edit-controls="true" :hide-search-button="true" :hide-copy-button="false" :hide-download-button="true" :hide-theme-button="false" /> </template>
Prop | Type | Default | Description |
---|---|---|---|
data | any | {} | JSON data to display |
editable | boolean | true | Enable editing capabilities |
theme | 'light' | 'dark' | 'light' | Theme preference |
defaultMode | 'tree' | 'text' | 'tree' | Default view mode |
showLineNumbers | boolean | false | Show line numbers in text mode |
maxDepth | number | 3 | Maximum depth to expand by default |
hideActionText | boolean | false | Hide button text labels (icons only) |
Prop | Type | Default | Description |
---|---|---|---|
hideHeader | boolean | false | Hide the entire menu bar (header) |
hideFooter | boolean | false | Hide the entire footer |
hideModeSwitcher | boolean | false | Hide the Tree/Text mode switcher |
hideTreeControls | boolean | false | Hide the Expand All/Collapse All buttons |
hideEditControls | boolean | false | Hide the Edit/Save/Cancel buttons |
hideSearchButton | boolean | false | Hide the Search button |
hideCopyButton | boolean | false | Hide the Copy button |
hideDownloadButton | boolean | false | Hide the Download button |
hideThemeButton | boolean | false | Hide the Theme toggle button |
Event | Payload | Description |
---|---|---|
update:data | newData: any | Data changed event |
node-click | node: JsonNode | Node clicked event |
node-expand | node: JsonNode | Node expanded event |
node-collapse | node: JsonNode | Node collapsed event |
edit-start | - | Edit mode started |
edit-save | data: any | Changes saved |
edit-cancel | - | Edit mode cancelled |
key-change | event: { node: JsonNode, oldKey: string, newKey: string } | Key name changed |
theme-change | theme: 'light' | 'dark' | Theme changed |
interface JsonNode { key: string; value: any; type: "string" | "number" | "boolean" | "object" | "array" | "null"; path: string[]; level: number; expanded?: boolean; children?: JsonNode[]; }
The component uses component-scoped CSS custom properties for theming, ensuring that theme changes only affect the JsonViewer component and do not interfere with your parent application's styling.
The theme is completely self-contained within the component:
Dynamic Theme Icons: The theme button automatically shows:
- π Moon icon when in light theme (click to switch to dark)
- βοΈ Sun icon when in dark theme (click to switch to light)
<template> <JsonViewer :theme="'dark'" <!-- Theme only affects this component --> v-model:data="jsonData" /> </template>
You can customize the appearance by overriding these CSS variables within the component scope:
.json-viewer { --bg-primary: #ffffff; --bg-secondary: #f8fafc; --bg-tertiary: #f1f5f9; --text-primary: #1e293b; --text-secondary: #64748b; --border-color: #e2e8f0; --accent-color: #3b82f6; --hover-color: #f1f5f9; --success-color: #10b981; --error-color: #ef4444; --warning-color: #f59e0b; }
When you use this component in other projects, the theme will only affect the component itself:
<template> <div> <!-- This header won't be affected by theme changes --> <header class="my-app-header"> <h1>My Application</h1> </header> <!-- Only this component will change theme --> <JsonViewer :theme="componentTheme" v-model:data="jsonData" @theme-change="handleThemeChange" /> <!-- This footer also won't be affected --> <footer class="my-app-footer"> <p>My Application Footer</p> </footer> </div> </template> <script setup> const componentTheme = ref('light'); const handleThemeChange = (newTheme) => { componentTheme.value = newTheme; // Theme only affects the JsonViewer component // Your app's global styling remains unchanged }; </script>
Benefits:
- β No Global Side Effects - Theme changes only affect the component
- β Better Encapsulation - Component manages its own appearance
- β Easier Integration - No conflicts with parent project's theme system
- β Reusable - Can be used in any project without affecting global styles
# Clone the repository git clone https://github.com/jeevan-lal/vue3-json-viewer.git # Install dependencies npm install # Start development server npm run dev
# Build the library component (for npm publishing) npm run build # Build the demo app to ./preview folder npm run build:demo # Preview the built demo app npm run preview
-
npm run build
β Createsdist/
folder with library files:json-viewer.umd.js
- UMD bundlejson-viewer.mjs
- ES module bundlestyle.css
- Component styles
-
npm run build:demo
β Createspreview/
folder with demo app:index.html
- Demo pageassets/
- Bundled CSS and JavaScript
# Build for production npm run build # Preview production build npm run preview
# Run ESLint npm run lint # Type check npm run type-check
Run the test suite:
npm run test
- Chrome β₯ 87
- Firefox β₯ 78
- Safari β₯ 14
- Edge β₯ 88
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature
) - Commit your changes (
git commit -m 'Add some AmazingFeature'
) - Push to the branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Problem: Theme changes not visible in your project
Solution: The component now uses component-only theming. Make sure you're passing the theme prop correctly:
<!-- β
Correct - Theme will work --> <JsonViewer :theme="'dark'" v-model:data="jsonData" /> <!-- β Incorrect - No theme prop --> <JsonViewer v-model:data="jsonData" />
Problem: Theme changes affecting your entire application
Solution: This shouldn't happen anymore! The component is now completely self-contained. If you're still experiencing issues, make sure you're using the latest version.
If you have any questions or need help, please:
- Check the documentation
- Search existing issues
- Create a new issue
Made with β€οΈ and Vue 3