diff --git a/README.md b/README.md
index 38a308e..37a6296 100644
--- a/README.md
+++ b/README.md
@@ -106,31 +106,32 @@ plugins: [
 
 ## Props
 
-| Property                  | Description                                                                     | Type                              | Default |
-|---------------------------|---------------------------------------------------------------------------------|-----------------------------------| ------- |
-| data(v-model)             | JSON data, support v-model when use editable                                    | JSON object                       | -       |
-| collapsedNodeLength       | Objects or arrays which length is greater than this threshold will be collapsed | number                            | -       |
-| deep                      | Paths greater than this depth will be collapsed                                 | number                            | -       |
-| showLength                | Show the length when collapsed                                                  | boolean                           | false   |
-| showLine                  | Show the line                                                                   | boolean                           | true    |
-| showLineNumber            | Show the line number                                                            | boolean                           | false   |
-| showIcon                  | Show the icon                                                                   | boolean                           | false   |
-| showDoubleQuotes          | Show doublequotes on key                                                        | boolean                           | true    |
-| virtual                   | Use virtual scroll                                                              | boolean                           | false   |
-| height                    | The height of list when using virtual                                           | number                            | 400     |
-| itemHeight                | The height of node when using virtual                                           | number                            | 20      |
-| selectedValue(v-model)    | Selected data path                                                              | string, array                     | -       |
-| rootPath                  | Root data path                                                                  | string                            | `root`  |
-| nodeSelectable            | Defines whether a node supports selection                                       | (node) => boolean                 | -       |
-| selectableType            | Support path select, default none                                               | `multiple` \| `single`            | -       |
-| showSelectController      | Show the select controller                                                      | boolean                           | false   |
-| selectOnClickNode         | Trigger select when click node                                                  | boolean                           | true    |
-| highlightSelectedNode     | Support highlighting selected nodes                                             | boolean                           | true    |
-| collapsedOnClickBrackets  | Support click brackets to collapse                                              | boolean                           | true    |
-| renderNodeKey             | render node key, or use slot #renderNodeKey                                     | ({ node, defaultKey }) => vNode   | -       |
-| renderNodeValue           | render node value, or use slot #renderNodeValue                                 | ({ node, defaultValue }) => vNode | -       |
-| editable                  | Support editable                                                                | boolean                           | false   |
-| editableTrigger           | Trigger                                                                         | `click` \| `dblclick`             | `click` |
+| Property                 | Description                                                                                                             | Type                              | Default |
+| ------------------------ | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------- |
+| data(v-model)            | JSON data, support v-model when use editable                                                                            | JSON object                       | -       |
+| collapsedNodeLength      | Objects or arrays which length is greater than this threshold will be collapsed                                         | number                            | -       |
+| deep                     | Paths greater than this depth will be collapsed                                                                         | number                            | -       |
+| showLength               | Show the length when collapsed                                                                                          | boolean                           | false   |
+| showLine                 | Show the line                                                                                                           | boolean                           | true    |
+| showLineNumber           | Show the line number                                                                                                    | boolean                           | false   |
+| showIcon                 | Show the icon                                                                                                           | boolean                           | false   |
+| showDoubleQuotes         | Show doublequotes on key                                                                                                | boolean                           | true    |
+| virtual                  | Use virtual scroll                                                                                                      | boolean                           | false   |
+| height                   | The height of list when using virtual                                                                                   | number                            | 400     |
+| itemHeight               | The height of node when using virtual                                                                                   | number                            | 20      |
+| selectedValue(v-model)   | Selected data path                                                                                                      | string, array                     | -       |
+| rootPath                 | Root data path                                                                                                          | string                            | `root`  |
+| nodeSelectable           | Defines whether a node supports selection                                                                               | (node) => boolean                 | -       |
+| selectableType           | Support path select, default none                                                                                       | `multiple` \| `single`            | -       |
+| showSelectController     | Show the select controller                                                                                              | boolean                           | false   |
+| selectOnClickNode        | Trigger select when click node                                                                                          | boolean                           | true    |
+| highlightSelectedNode    | Support highlighting selected nodes                                                                                     | boolean                           | true    |
+| collapsedOnClickBrackets | Support click brackets to collapse                                                                                      | boolean                           | true    |
+| renderNodeKey            | render node key, or use slot #renderNodeKey                                                                             | ({ node, defaultKey }) => vNode   | -       |
+| renderNodeValue          | render node value, or use slot #renderNodeValue                                                                         | ({ node, defaultValue }) => vNode | -       |
+| editable                 | Support editable                                                                                                        | boolean                           | false   |
+| editableTrigger          | Trigger                                                                                                                 | `click` \| `dblclick`             | `click` |
+| theme                    | Sets the theme of the component. Options are 'light' or 'dark', with dark mode enhancing visibility on dark backgrounds | `'light' \| 'dark'`               | `light` |
 
 ## Events
 
@@ -145,7 +146,7 @@ plugins: [
 
 | Slot Name       | Description       | Parameters             |
 | --------------- | ----------------- | ---------------------- |
-| renderNodeKey   | render node key   | { node, defaultKey }        |
+| renderNodeKey   | render node key   | { node, defaultKey }   |
 | renderNodeValue | render node value | { node, defaultValue } |
 
 ## Contributors
diff --git a/example/App.tsx b/example/App.tsx
index 730fd7f..44b4f8b 100644
--- a/example/App.tsx
+++ b/example/App.tsx
@@ -1,10 +1,11 @@
-import { defineComponent, reactive } from 'vue';
+import { defineComponent, reactive, provide, onMounted, watch } from 'vue';
 import Basic from './Basic.vue';
 import VirtualList from './VirtualList.vue';
 import SelectControl from './SelectControl.vue';
 import Editable from './Editable.vue';
 // import Tsx from './Tsx';
 import './styles.less';
+import { MoonIcon, SunIcon } from './Icons';
 
 const list = [
   {
@@ -41,6 +42,12 @@ export default defineComponent({
       opened: [list[0].key],
     });
 
+    const globalDarkModeState = reactive({
+      isDarkMode: window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches,
+    });
+
+    provide('darkModeState', globalDarkModeState);
+
     const onActiveChange = (key: string) => {
       state.activeKey = key;
       if (!state.opened.includes(key)) {
@@ -48,17 +55,35 @@ export default defineComponent({
       }
     };
 
+    const toggleDarkMode = () => {
+      globalDarkModeState.isDarkMode = !globalDarkModeState.isDarkMode;
+    };
+
+    onMounted(() => {
+      document.body.classList.toggle('dark-mode', globalDarkModeState.isDarkMode);
+    });
+
+    watch(
+      () => globalDarkModeState.isDarkMode,
+      newVal => {
+        document.body.classList.toggle('dark-mode', newVal);
+      },
+      { immediate: true },
+    );
+
     return {
       state,
       onActiveChange,
+      toggleDarkMode,
+      globalDarkModeState,
     };
   },
 
   render() {
-    const { state, onActiveChange } = this;
+    const { state, onActiveChange, toggleDarkMode, globalDarkModeState } = this;
 
     return (
-      <div class="example">
+      <div class={`example ${state.isDarkMode ? 'dark-mode' : ''}`}>
         <h1>Vue Json Pretty</h1>
         <p>
           Welcome to the demo space of Vue Json Pretty, here we provide the following different
@@ -67,15 +92,20 @@ export default defineComponent({
 
         <div class="tabs">
           <div class="tabs-header">
-            {list.map(({ title, key }) => (
-              <div
-                key={key}
-                class={`tabs-header-item ${key === state.activeKey ? 'is-active' : ''}`}
-                onClick={() => onActiveChange(key)}
-              >
-                {title}
-              </div>
-            ))}
+            <div class="tabs-items-container">
+              {list.map(({ title, key }) => (
+                <div
+                  key={key}
+                  class={`tabs-header-item ${key === state.activeKey ? 'is-active' : ''}`}
+                  onClick={() => onActiveChange(key)}
+                >
+                  {title}
+                </div>
+              ))}
+            </div>
+            <div class="dark-mode-toggle" onClick={toggleDarkMode}>
+              {globalDarkModeState.isDarkMode ? <SunIcon /> : <MoonIcon />}
+            </div>
           </div>
 
           <div class="tabs-content">
diff --git a/example/Basic.vue b/example/Basic.vue
index ae8d500..64df3a1 100644
--- a/example/Basic.vue
+++ b/example/Basic.vue
@@ -2,7 +2,7 @@
   <div class="example-box">
     <div class="block">
       <h3>JSON:</h3>
-      <textarea v-model="state.val" />
+      <textarea :class="{ 'dark-textarea': globalDarkModeState }" v-model="state.val"></textarea>
 
       <h3>Options:</h3>
       <div class="options">
@@ -46,6 +46,13 @@
           <label>setPathCollapsible</label>
           <input v-model="state.setPathCollapsible" type="checkbox" />
         </div>
+        <div>
+          <label>theme</label>
+          <select v-model="localDarkMode">
+            <option value="light">light</option>
+            <option value="dark">dark</option>
+          </select>
+        </div>
       </div>
 
       <h3>Slots:</h3>
@@ -63,6 +70,7 @@
     <div class="block">
       <h3>vue-json-pretty:</h3>
       <vue-json-pretty
+        :theme="localDarkMode"
         :data="state.data"
         :deep="state.deep"
         :path-collapsible="state.setPathCollapsible ? pathCollapsible : undefined"
@@ -95,6 +103,7 @@
 
 <script>
 import { defineComponent, reactive, watch } from 'vue';
+import { useDarkMode } from './useDarkMode';
 import VueJsonPretty from 'src';
 
 const defaultData = {
@@ -147,6 +156,8 @@ export default defineComponent({
       showKeyValueSpace: true,
     });
 
+    const { localDarkMode, toggleLocalDarkMode, globalDarkModeState } = useDarkMode();
+
     const pathCollapsible = node => {
       return node.key === 'members';
     };
@@ -165,6 +176,9 @@ export default defineComponent({
     return {
       state,
       pathCollapsible,
+      localDarkMode,
+      toggleLocalDarkMode,
+      globalDarkModeState,
     };
   },
 });
diff --git a/example/Editable.vue b/example/Editable.vue
index e4ed8b8..c339f31 100644
--- a/example/Editable.vue
+++ b/example/Editable.vue
@@ -2,7 +2,7 @@
   <div class="example-box">
     <div class="block">
       <h3>JSON:</h3>
-      <textarea v-model="state.val" />
+      <textarea :class="{ 'dark-textarea': globalDarkModeState }" v-model="state.val"></textarea>
 
       <h3>Options:</h3>
       <div class="options">
@@ -34,11 +34,19 @@
           </select>
         </div>
       </div>
+      <div>
+        <label>theme</label>
+        <select v-model="localDarkMode">
+          <option value="light">light</option>
+          <option value="dark">dark</option>
+        </select>
+      </div>
     </div>
     <div class="block">
       <h3>vue-json-pretty:</h3>
       <vue-json-pretty
         v-model:data="state.data"
+        :theme="localDarkMode"
         :deep="state.deep"
         :show-double-quotes="true"
         :show-line="state.showLine"
@@ -53,6 +61,7 @@
 <script>
 import { defineComponent, reactive, watch } from 'vue';
 import VueJsonPretty from 'src';
+import { useDarkMode } from './useDarkMode';
 
 const defaultData = {
   status: 200,
@@ -98,6 +107,8 @@ export default defineComponent({
       deep: 3,
     });
 
+    const { localDarkMode, toggleLocalDarkMode, globalDarkModeState } = useDarkMode();
+
     watch(
       () => state.val,
       newVal => {
@@ -122,7 +133,11 @@ export default defineComponent({
 
     return {
       state,
+      localDarkMode,
+      toggleLocalDarkMode,
+      globalDarkModeState,
     };
   },
 });
 </script>
+./useDarkMode
diff --git a/example/Icons.tsx b/example/Icons.tsx
new file mode 100644
index 0000000..fcf1407
--- /dev/null
+++ b/example/Icons.tsx
@@ -0,0 +1,39 @@
+export const SunIcon = () => (
+  <svg
+    xmlns="http://www.w3.org/2000/svg"
+    width="24"
+    height="24"
+    viewBox="0 0 24 24"
+    fill="none"
+    stroke="currentColor"
+    strokeWidth="2"
+    strokeLinecap="round"
+    strokeLinejoin="round"
+  >
+    <circle cx="12" cy="12" r="5"></circle>
+    <line x1="12" y1="1" x2="12" y2="3"></line>
+    <line x1="12" y1="21" x2="12" y2="23"></line>
+    <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
+    <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
+    <line x1="1" y1="12" x2="3" y2="12"></line>
+    <line x1="21" y1="12" x2="23" y2="12"></line>
+    <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
+    <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
+  </svg>
+);
+
+export const MoonIcon = () => (
+  <svg
+    xmlns="http://www.w3.org/2000/svg"
+    width="24"
+    height="24"
+    viewBox="0 0 24 24"
+    fill="none"
+    stroke="currentColor"
+    strokeWidth="2"
+    strokeLinecap="round"
+    strokeLinejoin="round"
+  >
+    <path d="M21 12.79A9 9 0 0112.21 3C11.66 3 11.11 3.05 10.58 3.15A9 9 0 1021 12.79z"></path>
+  </svg>
+);
diff --git a/example/SelectControl.vue b/example/SelectControl.vue
index 32a7196..a71755c 100644
--- a/example/SelectControl.vue
+++ b/example/SelectControl.vue
@@ -2,7 +2,7 @@
   <div class="example-box">
     <div class="block">
       <h3>JSON:</h3>
-      <textarea v-model="state.val" />
+      <textarea :class="{ 'dark-textarea': globalDarkModeState }" v-model="state.val"></textarea>
 
       <h3>Options:</h3>
       <div class="options">
@@ -57,6 +57,13 @@
             <option :value="4">4</option>
           </select>
         </div>
+        <div>
+          <label>theme</label>
+          <select v-model="localDarkMode">
+            <option value="light">light</option>
+            <option value="dark">dark</option>
+          </select>
+        </div>
       </div>
       <h3>v-model:selectedValue:</h3>
       <div>{{ state.selectedValue }}</div>
@@ -68,6 +75,7 @@
       <vue-json-pretty
         v-if="state.renderOK"
         v-model:selectedValue="state.selectedValue"
+        :theme="localDarkMode"
         :data="state.data"
         :root-path="state.rootPath"
         :deep="state.deep"
@@ -94,6 +102,7 @@
 <script>
 import { defineComponent, reactive, watch, nextTick } from 'vue';
 import VueJsonPretty from 'src';
+import { useDarkMode } from './useDarkMode';
 
 const defaultData = {
   status: 200,
@@ -148,6 +157,8 @@ export default defineComponent({
       showIcon: false,
     });
 
+    const { localDarkMode, toggleLocalDarkMode, globalDarkModeState } = useDarkMode();
+
     const handleNodeClick = node => {
       state.node = node;
     };
@@ -186,6 +197,9 @@ export default defineComponent({
       state,
       handleNodeClick,
       handleAll,
+      localDarkMode,
+      toggleLocalDarkMode,
+      globalDarkModeState,
     };
   },
 });
diff --git a/example/VirtualList.vue b/example/VirtualList.vue
index a8018de..710bd26 100644
--- a/example/VirtualList.vue
+++ b/example/VirtualList.vue
@@ -2,7 +2,7 @@
   <div class="example-box">
     <div class="block">
       <h3>JSON:</h3>
-      <textarea v-model="state.val" />
+      <textarea :class="{ 'dark-textarea': globalDarkModeState }" v-model="state.val"></textarea>
 
       <h3>Options:</h3>
       <div class="options">
@@ -34,10 +34,18 @@
           </select>
         </div>
       </div>
+      <div>
+        <label>theme</label>
+        <select v-model="localDarkMode">
+          <option value="light">light</option>
+          <option value="dark">dark</option>
+        </select>
+      </div>
     </div>
     <div class="block">
       <h3>vue-json-pretty(10000+ items):</h3>
       <vue-json-pretty
+        :theme="localDarkMode"
         :collapsed-node-length="state.collapsedNodeLength"
         :virtual="true"
         :item-height="+state.itemHeight"
@@ -53,6 +61,7 @@
 <script>
 import { defineComponent, reactive, watch } from 'vue';
 import VueJsonPretty from 'src';
+import { useDarkMode } from './useDarkMode';
 
 const defaultData = {
   status: 200,
@@ -86,6 +95,8 @@ export default defineComponent({
       itemHeight: 20,
     });
 
+    const { localDarkMode, toggleLocalDarkMode, globalDarkModeState } = useDarkMode();
+
     watch(
       () => state.val,
       newVal => {
@@ -99,6 +110,9 @@ export default defineComponent({
 
     return {
       state,
+      localDarkMode,
+      toggleLocalDarkMode,
+      globalDarkModeState,
     };
   },
 });
diff --git a/example/styles.less b/example/styles.less
index 6c0d867..4db97c7 100644
--- a/example/styles.less
+++ b/example/styles.less
@@ -1,4 +1,7 @@
 @primary-color: #1890ff;
+@dark-background-color: darken(#333, 5%);
+@dark-text-color: #fff;
+@dark-border-color: #555;
 
 * {
   box-sizing: border-box;
@@ -7,37 +10,59 @@
 html,
 body {
   margin: 0;
+  transition: background-color 0.3s, color 0.3s;
 }
 
 body {
   font-size: 14px;
   background-color: #f9f9f9;
+
+  &.dark-mode {
+    background-color: @dark-background-color;
+    color: @dark-text-color;
+  }
 }
 
 .tabs-header {
   display: flex;
+  justify-content: space-between;
   margin-bottom: 20px;
   border-bottom: 1px solid #ccc;
 }
 
-.tabs-header-item {
-  position: relative;
-  margin-right: 20px;
-  padding: 8px 0;
-  cursor: pointer;
-  transition: color 0.3s;
-
-  &:hover,
-  &.is-active {
-    color: @primary-color;
-
-    &:after {
-      border-bottom: 2px solid @primary-color;
-      content: '';
-      width: 100%;
-      position: absolute;
-      left: 0;
-      bottom: -1px;
+.tabs-items-container {
+  display: flex;
+
+  .tabs-header-item {
+    position: relative;
+    margin-right: 20px;
+    padding: 8px 0;
+    cursor: pointer;
+    transition: color 0.3s;
+
+    &:hover,
+    &.is-active {
+      color: @primary-color;
+
+      &:after {
+        border-bottom: 2px solid @primary-color;
+        content: '';
+        width: 100%;
+        position: absolute;
+        left: 0;
+        bottom: -1px;
+      }
+    }
+    body.dark-mode & {
+      color: @dark-text-color;
+      &:hover,
+      &.is-active {
+        color: lighten(@primary-color, 20%);
+
+        &:after {
+          border-bottom: 2px solid lighten(@primary-color, 20%);
+        }
+      }
     }
   }
 }
@@ -96,3 +121,9 @@ body {
     text-overflow: ellipsis;
   }
 }
+
+.dark-textarea {
+  background-color: #333;
+  color: #fff;
+  border-color: #444;
+}
diff --git a/example/useDarkMode.ts b/example/useDarkMode.ts
new file mode 100644
index 0000000..66abe61
--- /dev/null
+++ b/example/useDarkMode.ts
@@ -0,0 +1,22 @@
+import { inject, ref, watch } from 'vue';
+
+export function useDarkMode() {
+  const darkModeState = inject('darkModeState');
+  const globalDarkModeState = ref(darkModeState.isDarkMode);
+  const localDarkMode = ref(darkModeState.isDarkMode ? 'dark' : 'light');
+
+  watch(
+    () => darkModeState.isDarkMode,
+    newVal => {
+      localDarkMode.value = newVal ? 'dark' : 'light';
+      globalDarkModeState.value = newVal;
+    },
+  );
+
+  const toggleLocalDarkMode = () => {
+    darkModeState.isDarkMode = !darkModeState.isDarkMode;
+    localDarkMode.value = darkModeState.isDarkMode ? 'dark' : 'light';
+  };
+
+  return { localDarkMode, toggleLocalDarkMode, globalDarkModeState };
+}
diff --git a/src/components/Tree/index.tsx b/src/components/Tree/index.tsx
index 8edab29..6957e8a 100644
--- a/src/components/Tree/index.tsx
+++ b/src/components/Tree/index.tsx
@@ -70,6 +70,10 @@ export default defineComponent({
     onSelectedChange: {
       type: Function as PropType<(newVal: string | string[], oldVal: string | string[]) => void>,
     },
+    theme: {
+      type: String as PropType<'light' | 'dark'>,
+      default: 'light',
+    },
   },
 
   slots: ['renderNodeKey', 'renderNodeValue'],
@@ -281,6 +285,7 @@ export default defineComponent({
             key={item.id}
             node={item}
             collapsed={!!state.hiddenPaths[item.path]}
+            theme={props.theme}
             showDoubleQuotes={props.showDoubleQuotes}
             showLength={props.showLength}
             checked={selectedPaths.value.includes(item.path)}
@@ -316,6 +321,7 @@ export default defineComponent({
           class={{
             'vjs-tree': true,
             'is-virtual': props.virtual,
+            dark: props.theme === 'dark',
           }}
           onScroll={props.virtual ? handleTreeScroll : undefined}
           style={
diff --git a/src/components/TreeNode/index.tsx b/src/components/TreeNode/index.tsx
index fa5b0bb..6c6a27c 100644
--- a/src/components/TreeNode/index.tsx
+++ b/src/components/TreeNode/index.tsx
@@ -64,6 +64,10 @@ export const treeNodePropsPass = {
     type: Boolean,
     default: false,
   },
+  theme: {
+    type: String as PropType<'light' | 'dark'>,
+    default: 'light',
+  },
   showKeyValueSpace: {
     type: Boolean,
     default: true,
@@ -213,6 +217,7 @@ export default defineComponent({
             'has-selector': props.showSelectController,
             'has-carets': props.showIcon,
             'is-highlight': props.highlightSelectedNode && props.checked,
+            dark: props.theme === 'dark',
           }}
           onClick={handleNodeClick}
           style={props.style}
diff --git a/src/components/TreeNode/styles.less b/src/components/TreeNode/styles.less
index 6748a73..57292f9 100644
--- a/src/components/TreeNode/styles.less
+++ b/src/components/TreeNode/styles.less
@@ -35,6 +35,13 @@
       border-left: 1px dashed @border-color;
     }
   }
+
+  &.dark {
+    &.is-highlight,
+    &:hover {
+      background-color: @highlight-bg-color-dark;
+    }
+  }
 }
 
 .@{css-prefix}-node-index {
diff --git a/src/themes.less b/src/themes.less
index d857ba0..96d100d 100644
--- a/src/themes.less
+++ b/src/themes.less
@@ -6,7 +6,7 @@
 @color-info: #1d8ce0;
 @color-error: #ff4949;
 @color-success: #13ce66;
-@color-nil: #D55FDE;
+@color-nil: #d55fde;
 
 /* field values color */
 @color-string: @color-success;
@@ -17,6 +17,7 @@
 
 /* highlight */
 @highlight-bg-color: #e6f7ff;
+@highlight-bg-color-dark: #2e4558;
 
 /* comment */
 @comment-color: #bfcbd9;