Skip to content

Commit cd0e0b8

Browse files
committed
feat: Add light/dark mode toggle, #6
1 parent 17ba582 commit cd0e0b8

File tree

1 file changed

+98
-7
lines changed

1 file changed

+98
-7
lines changed

toc-bar.user.js

Lines changed: 98 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
// @match *://mp.weixin.qq.com/s*
1515
// @match *://cnodejs.org/topic/*
1616
// @match *://*zcfy.cc/article/*
17-
// @match *://juejin.im/entry/*
17+
// @match *://juejin.cn/post/*
1818
// @match *://dev.to/*/*
1919
// @exclude *://dev.to/settings/*
2020
// @match *://web.dev/*
2121
// @match *://medium.com/*
22+
// @exclude *://medium.com/media/*
23+
// @match *://itnext.io/*
2224
// @match *://www.infoq.cn/article/*
2325
// @match *://towardsdatascience.com/*
2426
// @match *://hackernoon.com/*
@@ -257,10 +259,14 @@
257259
/** 宽度,也用于计算拖动时的最小 right */
258260
const TOC_BAR_WIDTH = 340
259261

262+
const TOC_BAR_DEFAULT_ACTIVE_COLOR = '#54BC4B';
263+
260264
// ---------------- TocBar ----------------------
261265
const TOC_BAR_STYLE = `
262266
.toc-bar {
263-
--toc-bar-active-color: #54BC4B;
267+
--toc-bar-active-color: ${TOC_BAR_DEFAULT_ACTIVE_COLOR};
268+
--toc-bar-text-color: #333;
269+
--toc-bar-background-color: #FEFEFE;
264270
265271
position: fixed;
266272
z-index: 9000;
@@ -273,15 +279,24 @@
273279
box-shadow: 0 1px 3px #DDD;
274280
border-radius: 4px;
275281
transition: width 0.2s ease;
276-
color: #333;
277-
background: #FEFEFE;
282+
color: var(--toc-bar-text-color);
283+
background: var(--toc-bar-background-color);
278284
279285
user-select:none;
280286
-moz-user-select:none;
281287
-webkit-user-select: none;
282288
-ms-user-select: none;
283289
}
284290
291+
.toc-bar[colorscheme="dark"] {
292+
--toc-bar-text-color: #fafafa;
293+
--toc-bar-background-color: #333;
294+
}
295+
.toc-bar[colorscheme="dark"] svg {
296+
fill: var(--toc-bar-text-color);
297+
stroke: var(--toc-bar-text-color);
298+
}
299+
285300
.toc-bar.toc-bar--collapsed {
286301
width: 30px;
287302
height: 30px;
@@ -328,6 +343,17 @@
328343
vertical-align: top;
329344
}
330345
346+
.toc-bar__actions {
347+
align-items: center;
348+
}
349+
.toc-bar__actions .toc-bar__icon-btn {
350+
margin-left: 1em;
351+
}
352+
353+
.toc-bar__scheme {
354+
transform: translateY(-1px) scale(1.1);
355+
}
356+
331357
.toc-bar__header-left {
332358
align-items: center;
333359
}
@@ -407,7 +433,7 @@ a.toc-link {
407433
}
408434
409435
.toc-link::before {
410-
background-color: #EEE;
436+
background-color: var(--toc-bar-background-color);
411437
content: ' ';
412438
display: inline-block;
413439
height: inherit;
@@ -425,6 +451,8 @@ a.toc-link {
425451

426452
const TOCBOT_CONTAINTER_CLASS = 'toc-bar__toc'
427453

454+
const DARKMODE_KEY = 'tocbar-darkmode'
455+
428456
/**
429457
* @class
430458
*/
@@ -461,6 +489,14 @@ a.toc-link {
461489
if (GM_getValue('tocbar-hidden', false)) {
462490
this.toggle(false)
463491
}
492+
493+
const isDark = Boolean(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
494+
/** @type {Boolean} */
495+
this.isDarkMode = isDark
496+
497+
if (GM_getValue(DARKMODE_KEY, false)) {
498+
this.toggleScheme(true)
499+
}
464500
}
465501

466502
const REFRESH_ICON = `<svg t="1593614403764" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5002" width="200" height="200"><path d="M918 702.8 918 702.8c45.6-98.8 52-206 26-303.6-30-112.4-104-212.8-211.6-273.6L780 23.2l-270.8 70.8 121.2 252.4 50-107.6c72.8 44.4 122.8 114.4 144 192.8 18.8 70.8 14.4 147.6-18.8 219.6-42 91.2-120.8 153.6-210.8 177.6-13.2 3.6-26.4 6-39.6 8l56 115.6c5.2-1.2 10.4-2.4 16-4C750.8 915.2 860 828.8 918 702.8L918 702.8M343.2 793.2c-74-44.4-124.8-114.8-146-194-18.8-70.8-14.4-147.6 18.8-219.6 42-91.2 120.8-153.6 210.8-177.6 14.8-4 30-6.8 45.6-8.8l-55.6-116c-7.2 1.6-14.8 3.2-22 5.2-124 33.2-233.6 119.6-291.2 245.6-45.6 98.8-52 206-26 303.2l0 0.4c30.4 113.2 105.2 214 213.6 274.8l-45.2 98 270.4-72-122-252L343.2 793.2 343.2 793.2M343.2 793.2 343.2 793.2z" p-id="5003"></path></svg>`
@@ -480,6 +516,38 @@ a.toc-link {
480516
</svg>
481517
`
482518

519+
const LIGHT_ICON = `
520+
<?xml version="1.0" encoding="iso-8859-1"?>
521+
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
522+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
523+
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
524+
viewBox="0 0 181.328 181.328" style="enable-background:new 0 0 181.328 181.328;" xml:space="preserve" style="transform: translateY(-1px);">
525+
<g>
526+
<path d="M118.473,46.308V14.833c0-4.142-3.358-7.5-7.5-7.5H70.357c-4.142,0-7.5,3.358-7.5,7.5v31.474
527+
C51.621,54.767,44.34,68.214,44.34,83.331c0,25.543,20.781,46.324,46.324,46.324s46.324-20.781,46.324-46.324
528+
C136.988,68.215,129.708,54.769,118.473,46.308z M77.857,22.333h25.615v16.489c-4.071-1.174-8.365-1.815-12.809-1.815
529+
c-4.443,0-8.736,0.642-12.807,1.814V22.333z M90.664,114.655c-17.273,0-31.324-14.052-31.324-31.324
530+
c0-17.272,14.052-31.324,31.324-31.324s31.324,14.052,31.324,31.324C121.988,100.604,107.937,114.655,90.664,114.655z"/>
531+
<path d="M40.595,83.331c0-4.142-3.358-7.5-7.5-7.5H7.5c-4.142,0-7.5,3.358-7.5,7.5c0,4.142,3.358,7.5,7.5,7.5h25.595
532+
C37.237,90.831,40.595,87.473,40.595,83.331z"/>
533+
<path d="M173.828,75.831h-25.595c-4.142,0-7.5,3.358-7.5,7.5c0,4.142,3.358,7.5,7.5,7.5h25.595c4.142,0,7.5-3.358,7.5-7.5
534+
C181.328,79.189,177.97,75.831,173.828,75.831z"/>
535+
<path d="M44.654,47.926c1.464,1.465,3.384,2.197,5.303,2.197c1.919,0,3.839-0.732,5.303-2.197c2.929-2.929,2.929-7.678,0-10.606
536+
L37.162,19.222c-2.929-2.93-7.678-2.929-10.606,0c-2.929,2.929-2.929,7.678,0,10.606L44.654,47.926z"/>
537+
<path d="M136.674,118.735c-2.93-2.929-7.678-2.928-10.607,0c-2.929,2.929-2.928,7.678,0,10.607l18.1,18.098
538+
c1.465,1.464,3.384,2.196,5.303,2.196c1.919,0,3.839-0.732,5.304-2.197c2.929-2.929,2.928-7.678,0-10.607L136.674,118.735z"/>
539+
<path d="M44.654,118.736l-18.099,18.098c-2.929,2.929-2.929,7.677,0,10.607c1.464,1.465,3.384,2.197,5.303,2.197
540+
c1.919,0,3.839-0.732,5.303-2.197l18.099-18.098c2.929-2.929,2.929-7.677,0-10.606C52.332,115.807,47.583,115.807,44.654,118.736z"
541+
/>
542+
<path d="M131.371,50.123c1.919,0,3.839-0.732,5.303-2.196l18.1-18.098c2.929-2.929,2.929-7.678,0-10.607
543+
c-2.929-2.928-7.678-2.929-10.607-0.001l-18.1,18.098c-2.929,2.929-2.929,7.678,0,10.607
544+
C127.532,49.391,129.452,50.123,131.371,50.123z"/>
545+
<path d="M90.664,133.4c-4.142,0-7.5,3.358-7.5,7.5v25.595c0,4.142,3.358,7.5,7.5,7.5c4.142,0,7.5-3.358,7.5-7.5V140.9
546+
C98.164,136.758,94.806,133.4,90.664,133.4z"/>
547+
</g>
548+
</svg>
549+
`
550+
483551
TocBar.prototype = {
484552
/**
485553
* @method TocBar
@@ -494,7 +562,10 @@ a.toc-link {
494562
</div>
495563
<div class="toc-bar__title hidden-when-collapsed">TOC Bar</div>
496564
</div>
497-
<div class="toc-bar__actions hidden-when-collapsed">
565+
<div class="toc-bar__actions flex hidden-when-collapsed">
566+
<div class="toc-bar__scheme toc-bar__icon-btn" title="Toggle Light/Dark Mode">
567+
${LIGHT_ICON}
568+
</div>
498569
<div class="toc-bar__refresh toc-bar__icon-btn" title="Refresh TOC">
499570
${REFRESH_ICON}
500571
</div>
@@ -511,6 +582,11 @@ a.toc-link {
511582
refreshElement.addEventListener('click', () => {
512583
tocbot.refresh()
513584
})
585+
586+
const toggleSchemeElement = header.querySelector('.toc-bar__scheme')
587+
toggleSchemeElement.addEventListener('click', () => {
588+
this.toggleScheme()
589+
})
514590
// ---------------- header drag ----------------------
515591
const dragState = {
516592
startMouseX: 0,
@@ -640,10 +716,25 @@ a.toc-link {
640716
}
641717
this.visible = shouldShow
642718
},
719+
/**
720+
* Toggle light/dark scheme
721+
* @method TocBar
722+
*/
723+
toggleScheme(isDark) {
724+
const isDarkMode = typeof isDark === 'undefined' ? !this.isDarkMode: isDark
725+
this.element.setAttribute('colorscheme', isDarkMode ? 'dark': 'light')
726+
console.log('[toc-bar] toggle scheme', isDarkMode)
727+
this.isDarkMode = isDarkMode
728+
729+
GM_setValue(DARKMODE_KEY, isDarkMode)
730+
this.refreshStyle()
731+
},
643732
refreshStyle() {
644733
const themeColor = guessThemeColor()
645-
if (themeColor) {
734+
if (themeColor && !this.isDarkMode) {
646735
this.element.style.setProperty('--toc-bar-active-color', themeColor);
736+
} else if (this.isDarkMode) {
737+
this.element.style.setProperty('--toc-bar-active-color', TOC_BAR_DEFAULT_ACTIVE_COLOR);
647738
}
648739
},
649740
}

0 commit comments

Comments
 (0)