Skip to content

Commit 8cd319b

Browse files
committed
feat: add basic darkmode support
1 parent 33c7ed8 commit 8cd319b

File tree

10 files changed

+151
-30
lines changed

10 files changed

+151
-30
lines changed

example/App.tsx

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { defineComponent, reactive } from 'vue';
1+
import { defineComponent, reactive, provide, onMounted } from 'vue';
22
import Basic from './Basic.vue';
33
import VirtualList from './VirtualList.vue';
44
import SelectControl from './SelectControl.vue';
@@ -34,20 +34,67 @@ const list = [
3434
// },
3535
];
3636

37+
const SunIcon = () => (
38+
<svg
39+
xmlns="http://www.w3.org/2000/svg"
40+
width="24"
41+
height="24"
42+
viewBox="0 0 24 24"
43+
fill="none"
44+
stroke="currentColor"
45+
strokeWidth="2"
46+
strokeLinecap="round"
47+
strokeLinejoin="round"
48+
>
49+
<circle cx="12" cy="12" r="5"></circle>
50+
<line x1="12" y1="1" x2="12" y2="3"></line>
51+
<line x1="12" y1="21" x2="12" y2="23"></line>
52+
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
53+
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
54+
<line x1="1" y1="12" x2="3" y2="12"></line>
55+
<line x1="21" y1="12" x2="23" y2="12"></line>
56+
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
57+
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
58+
</svg>
59+
);
60+
61+
const MoonIcon = () => (
62+
<svg
63+
xmlns="http://www.w3.org/2000/svg"
64+
width="24"
65+
height="24"
66+
viewBox="0 0 24 24"
67+
fill="none"
68+
stroke="currentColor"
69+
strokeWidth="2"
70+
strokeLinecap="round"
71+
strokeLinejoin="round"
72+
>
73+
<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>
74+
</svg>
75+
);
76+
3777
export default defineComponent({
3878
setup() {
3979
const state = reactive({
4080
activeKey: list[0].key,
4181
opened: [list[0].key],
82+
isDarkMode: window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches,
4283
});
4384

85+
provide('darkModeState', state);
86+
4487
const onActiveChange = (key: string) => {
4588
state.activeKey = key;
4689
if (!state.opened.includes(key)) {
4790
state.opened.push(key);
4891
}
4992
};
5093

94+
onMounted(() => {
95+
document.body.classList.toggle('dark-mode', state.isDarkMode);
96+
});
97+
5198
return {
5299
state,
53100
onActiveChange,
@@ -57,8 +104,13 @@ export default defineComponent({
57104
render() {
58105
const { state, onActiveChange } = this;
59106

107+
const toggleDarkMode = () => {
108+
state.isDarkMode = !state.isDarkMode;
109+
document.body.classList.toggle('dark-mode', state.isDarkMode);
110+
};
111+
60112
return (
61-
<div class="example">
113+
<div class={`example ${state.isDarkMode ? 'dark-mode' : ''}`}>
62114
<h1>Vue Json Pretty</h1>
63115
<p>
64116
Welcome to the demo space of Vue Json Pretty, here we provide the following different
@@ -67,15 +119,20 @@ export default defineComponent({
67119

68120
<div class="tabs">
69121
<div class="tabs-header">
70-
{list.map(({ title, key }) => (
71-
<div
72-
key={key}
73-
class={`tabs-header-item ${key === state.activeKey ? 'is-active' : ''}`}
74-
onClick={() => onActiveChange(key)}
75-
>
76-
{title}
77-
</div>
78-
))}
122+
<div class="tabs-items-container">
123+
{list.map(({ title, key }) => (
124+
<div
125+
key={key}
126+
class={`tabs-header-item ${key === state.activeKey ? 'is-active' : ''}`}
127+
onClick={() => onActiveChange(key)}
128+
>
129+
{title}
130+
</div>
131+
))}
132+
</div>
133+
<div class="dark-mode-toggle" onClick={toggleDarkMode}>
134+
{state.isDarkMode ? <SunIcon /> : <MoonIcon />}
135+
</div>
79136
</div>
80137

81138
<div class="tabs-content">

example/Basic.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@
4646
<label>setPathCollapsible</label>
4747
<input v-model="state.setPathCollapsible" type="checkbox" />
4848
</div>
49+
<div>
50+
<label>darkMode</label>
51+
<input v-model="state.darkMode" type="checkbox" />
52+
</div>
4953
</div>
5054

5155
<h3>Slots:</h3>
@@ -63,6 +67,7 @@
6367
<div class="block">
6468
<h3>vue-json-pretty:</h3>
6569
<vue-json-pretty
70+
:darkMode="state.darkMode"
6671
:data="state.data"
6772
:deep="state.deep"
6873
:path-collapsible="state.setPathCollapsible ? pathCollapsible : undefined"

example/Editable.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,16 @@
3434
</select>
3535
</div>
3636
</div>
37+
<div>
38+
<label>darkMode</label>
39+
<input v-model="state.darkMode" type="checkbox" />
40+
</div>
3741
</div>
3842
<div class="block">
3943
<h3>vue-json-pretty:</h3>
4044
<vue-json-pretty
4145
v-model:data="state.data"
46+
:darkMode="state.darkMode"
4247
:deep="state.deep"
4348
:show-double-quotes="true"
4449
:show-line="state.showLine"

example/SelectControl.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@
5757
<option :value="4">4</option>
5858
</select>
5959
</div>
60+
<div>
61+
<label>darkMode</label>
62+
<input v-model="state.darkMode" type="checkbox" />
63+
</div>
6064
</div>
6165
<h3>v-model:selectedValue:</h3>
6266
<div>{{ state.selectedValue }}</div>
@@ -68,6 +72,7 @@
6872
<vue-json-pretty
6973
v-if="state.renderOK"
7074
v-model:selectedValue="state.selectedValue"
75+
:darkMode="state.darkMode"
7176
:data="state.data"
7277
:root-path="state.rootPath"
7378
:deep="state.deep"

example/VirtualList.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,15 @@
3434
</select>
3535
</div>
3636
</div>
37+
<div>
38+
<label>darkMode</label>
39+
<input v-model="state.darkMode" type="checkbox" />
40+
</div>
3741
</div>
3842
<div class="block">
3943
<h3>vue-json-pretty(10000+ items):</h3>
4044
<vue-json-pretty
45+
:darkMode="state.darkMode"
4146
:collapsed-node-length="state.collapsedNodeLength"
4247
:virtual="true"
4348
:item-height="+state.itemHeight"

example/styles.less

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
@primary-color: #1890ff;
2+
@dark-background-color: darken(#333, 5%);
3+
@dark-text-color: #fff;
4+
@dark-border-color: #555;
25

36
* {
47
box-sizing: border-box;
@@ -7,37 +10,59 @@
710
html,
811
body {
912
margin: 0;
13+
transition: background-color 0.3s, color 0.3s;
1014
}
1115

1216
body {
1317
font-size: 14px;
1418
background-color: #f9f9f9;
19+
20+
&.dark-mode {
21+
background-color: @dark-background-color;
22+
color: @dark-text-color;
23+
}
1524
}
1625

1726
.tabs-header {
1827
display: flex;
28+
justify-content: space-between;
1929
margin-bottom: 20px;
2030
border-bottom: 1px solid #ccc;
2131
}
2232

23-
.tabs-header-item {
24-
position: relative;
25-
margin-right: 20px;
26-
padding: 8px 0;
27-
cursor: pointer;
28-
transition: color 0.3s;
29-
30-
&:hover,
31-
&.is-active {
32-
color: @primary-color;
33-
34-
&:after {
35-
border-bottom: 2px solid @primary-color;
36-
content: '';
37-
width: 100%;
38-
position: absolute;
39-
left: 0;
40-
bottom: -1px;
33+
.tabs-items-container {
34+
display: flex;
35+
36+
.tabs-header-item {
37+
position: relative;
38+
margin-right: 20px;
39+
padding: 8px 0;
40+
cursor: pointer;
41+
transition: color 0.3s;
42+
43+
&:hover,
44+
&.is-active {
45+
color: @primary-color;
46+
47+
&:after {
48+
border-bottom: 2px solid @primary-color;
49+
content: '';
50+
width: 100%;
51+
position: absolute;
52+
left: 0;
53+
bottom: -1px;
54+
}
55+
}
56+
body.dark-mode & {
57+
color: @dark-text-color;
58+
&:hover,
59+
&.is-active {
60+
color: lighten(@primary-color, 20%);
61+
62+
&:after {
63+
border-bottom: 2px solid lighten(@primary-color, 20%);
64+
}
65+
}
4166
}
4267
}
4368
}

src/components/Tree/index.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ export default defineComponent({
7070
onSelectedChange: {
7171
type: Function as PropType<(newVal: string | string[], oldVal: string | string[]) => void>,
7272
},
73+
darkMode: {
74+
type: Boolean,
75+
default: false,
76+
},
7377
},
7478

7579
slots: ['renderNodeKey', 'renderNodeValue'],
@@ -281,6 +285,7 @@ export default defineComponent({
281285
key={item.id}
282286
node={item}
283287
collapsed={!!state.hiddenPaths[item.path]}
288+
darkMode={props.darkMode}
284289
showDoubleQuotes={props.showDoubleQuotes}
285290
showLength={props.showLength}
286291
checked={selectedPaths.value.includes(item.path)}
@@ -316,6 +321,7 @@ export default defineComponent({
316321
class={{
317322
'vjs-tree': true,
318323
'is-virtual': props.virtual,
324+
'dark-mode': props.darkMode,
319325
}}
320326
onScroll={props.virtual ? handleTreeScroll : undefined}
321327
style={

src/components/TreeNode/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ export const treeNodePropsPass = {
6464
type: Boolean,
6565
default: false,
6666
},
67+
darkMode: {
68+
type: Boolean,
69+
default: false,
70+
},
6771
showKeyValueSpace: {
6872
type: Boolean,
6973
default: true,
@@ -213,6 +217,7 @@ export default defineComponent({
213217
'has-selector': props.showSelectController,
214218
'has-carets': props.showIcon,
215219
'is-highlight': props.highlightSelectedNode && props.checked,
220+
'dark-mode': props.darkMode,
216221
}}
217222
onClick={handleNodeClick}
218223
style={props.style}

src/components/TreeNode/styles.less

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@
3535
border-left: 1px dashed @border-color;
3636
}
3737
}
38+
39+
&.dark-mode {
40+
&.is-highlight,
41+
&:hover {
42+
background-color: @highlight-bg-color-dark;
43+
}
44+
}
3845
}
3946

4047
.@{css-prefix}-node-index {

src/themes.less

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
@color-info: #1d8ce0;
77
@color-error: #ff4949;
88
@color-success: #13ce66;
9-
@color-nil: #D55FDE;
9+
@color-nil: #d55fde;
1010

1111
/* field values color */
1212
@color-string: @color-success;
@@ -17,6 +17,7 @@
1717

1818
/* highlight */
1919
@highlight-bg-color: #e6f7ff;
20+
@highlight-bg-color-dark: #2e4558;
2021

2122
/* comment */
2223
@comment-color: #bfcbd9;

0 commit comments

Comments
 (0)