feat: add night mode (#4)
This commit is contained in:
parent
a1b848bb55
commit
ba1db7db3e
5 changed files with 357 additions and 1 deletions
90
_includes/extensions/theme-toggle.html
Normal file
90
_includes/extensions/theme-toggle.html
Normal file
|
@ -0,0 +1,90 @@
|
|||
<div class="theme-toggle">
|
||||
<input type="checkbox" id="theme-switch">
|
||||
<label for="theme-switch">
|
||||
<div class="toggle"></div>
|
||||
<div class="names">
|
||||
<p class="light">Light</p>
|
||||
<p class="dark">Dark</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var sw = document.getElementById('theme-switch');
|
||||
var html = document.getElementsByTagName('html')[0];
|
||||
var themeData = loadThemeData();
|
||||
|
||||
function saveThemeData(data) {
|
||||
localStorage.setItem('theme', JSON.stringify(data));
|
||||
}
|
||||
|
||||
function loadThemeData() {
|
||||
var data = localStorage.getItem('theme');
|
||||
try {
|
||||
data = JSON.parse(data ? data : '');
|
||||
} catch(e) {
|
||||
data = { nightShift: null, autoToggleAt: 0 };
|
||||
saveThemeData(data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function handleThemeToggle(nightShift) {
|
||||
themeData.nightShift = nightShift;
|
||||
saveThemeData(themeData);
|
||||
html.dataset.theme = nightShift ? 'dark' : 'light';
|
||||
setTimeout(function() {
|
||||
sw.checked = nightShift ? true : false;
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function autoThemeToggle() {
|
||||
// Next time point of theme toggle
|
||||
var now = new Date();
|
||||
var toggleAt = new Date();
|
||||
var hours = now.getHours();
|
||||
var nightShift = hours >= 19 || hours <=7;
|
||||
|
||||
if (nightShift) {
|
||||
if (hours > 7) {
|
||||
toggleAt.setDate(toggleAt.getDate() + 1);
|
||||
}
|
||||
toggleAt.setHours(7);
|
||||
} else {
|
||||
toggleAt.setHours(19);
|
||||
}
|
||||
|
||||
toggleAt.setMinutes(0);
|
||||
toggleAt.setSeconds(0);
|
||||
toggleAt.setMilliseconds(0)
|
||||
|
||||
var delay = toggleAt.getTime() - now.getTime();
|
||||
|
||||
// auto toggle theme mode
|
||||
setTimeout(function() {
|
||||
handleThemeToggle(!nightShift);
|
||||
}, delay);
|
||||
|
||||
return {
|
||||
nightShift: nightShift,
|
||||
toggleAt: toggleAt.getTime()
|
||||
};
|
||||
}
|
||||
|
||||
var data = autoThemeToggle();
|
||||
|
||||
// Listen the theme toggle event
|
||||
sw.addEventListener('change', function(event) {
|
||||
handleThemeToggle(event.target.checked);
|
||||
});
|
||||
|
||||
// Toggle theme by local setting
|
||||
if (data.toggleAt > themeData.autoToggleAt) {
|
||||
themeData.autoToggleAt = data.toggleAt;
|
||||
handleThemeToggle(data.nightShift);
|
||||
} else {
|
||||
handleThemeToggle(themeData.nightShift);
|
||||
}
|
||||
})();
|
||||
</script>
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
{%- include extensions/hashlocate.html -%}
|
||||
|
||||
{%- include extensions/theme-toggle.html -%}
|
||||
|
||||
<main class="page-content" aria-label="Content">
|
||||
<div class="wrapper">
|
||||
{{ content }}
|
||||
|
|
79
_sass/misc/theme-toggle.scss
Normal file
79
_sass/misc/theme-toggle.scss
Normal file
|
@ -0,0 +1,79 @@
|
|||
.theme-toggle {
|
||||
position: relative;
|
||||
width: 102px;
|
||||
margin-top: 10px;
|
||||
margin-right: 60px;
|
||||
margin-left: auto;
|
||||
transition: 0.1s all ease-in-out;
|
||||
|
||||
label, .toggle {
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
background-color: rgba(120,120,120,.15);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
position: absolute;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 15px rgba(0,0,0,.15);
|
||||
transition: transform .2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
}
|
||||
|
||||
.names {
|
||||
font-size: 1em;
|
||||
font-weight: bolder;
|
||||
width: 76%;
|
||||
margin-left: 12%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.dark {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #acacac;
|
||||
margin-bottom: 0;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
[type="checkbox"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Toggle */
|
||||
[type="checkbox"]:checked ~ label .toggle {
|
||||
transform: translateX(100%);
|
||||
background-color: #34323D;
|
||||
}
|
||||
|
||||
[type="checkbox"]:checked ~ label .dark{
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[type="checkbox"]:checked ~ label .light{
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
@include media-query(1024px) {
|
||||
margin-right: 35px;
|
||||
}
|
||||
|
||||
@include media-query($on-palm) {
|
||||
width: 94px;
|
||||
margin-right: 20px;
|
||||
|
||||
.names {
|
||||
font-size: .85em;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -61,7 +61,8 @@ $on-laptop: 800px !default;
|
|||
@import
|
||||
"yat/base",
|
||||
"yat/layout",
|
||||
// "yat/syntax-highlighting",
|
||||
"yat/dark",
|
||||
"misc/theme-toggle",
|
||||
"misc/article-menu",
|
||||
"misc/common-list",
|
||||
"misc/google-translate"
|
||||
|
|
184
_sass/yat/_dark.scss
Normal file
184
_sass/yat/_dark.scss
Normal file
|
@ -0,0 +1,184 @@
|
|||
$dark-background-color: #0e0e0e !default;
|
||||
|
||||
html[data-theme="dark"] {
|
||||
|
||||
&[data-scroll-status='top'] {
|
||||
.site-footer-inner {
|
||||
border-top: solid 1px #2f2f2f !important;
|
||||
transition: 0s;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
color: #bbb;
|
||||
background-color: $dark-background-color;
|
||||
}
|
||||
|
||||
*:not(pre) > code {
|
||||
background-color: #545454;
|
||||
}
|
||||
|
||||
table {
|
||||
color: #9d9d9d;
|
||||
|
||||
th {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background-color: #111;
|
||||
}
|
||||
}
|
||||
|
||||
.site-header {
|
||||
background-color: #090909;
|
||||
|
||||
.site-brand {
|
||||
.site-brand-inner {
|
||||
&, &:visited {
|
||||
color: #f8f8f8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.site-nav .page-link {
|
||||
color: #f8f8f8;
|
||||
}
|
||||
|
||||
.ct-language-dropdown {
|
||||
color: #f8f8f8;
|
||||
background-color: $dark-background-color;
|
||||
}
|
||||
|
||||
.ct-language-selected, .ct-language-dropdown li:hover {
|
||||
background-color: #222 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.left-vsplit:before {
|
||||
background-color: #9a9a9a;
|
||||
}
|
||||
|
||||
.page-banner {
|
||||
.page-banner-img {
|
||||
& > *:first-child {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
.post-link {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.post-title {
|
||||
a:visited:after {
|
||||
background-color: $dark-background-color;
|
||||
}
|
||||
|
||||
a:after {
|
||||
color: $dark-background-color;
|
||||
}
|
||||
}
|
||||
|
||||
.post-list {
|
||||
& > li:not(:last-child) {
|
||||
border-bottom: 1px solid #545454;
|
||||
}
|
||||
}
|
||||
|
||||
.post-tags .post-tag:hover {
|
||||
color: #d7d7d7;
|
||||
}
|
||||
}
|
||||
|
||||
.page-segments {
|
||||
li {
|
||||
a {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
a:visited:after {
|
||||
background-color: $dark-background-color;
|
||||
}
|
||||
|
||||
a:after {
|
||||
color: $dark-background-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.post .post-content {
|
||||
img:not([raw]) {
|
||||
background-color: #ffffff33;
|
||||
}
|
||||
}
|
||||
|
||||
.post-related {
|
||||
& > *:first-child {
|
||||
color: #d7d7d7;
|
||||
}
|
||||
|
||||
a:visited:after {
|
||||
background-color: $dark-background-color;
|
||||
}
|
||||
|
||||
a:after {
|
||||
color: $dark-background-color;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
.common-list {
|
||||
li {
|
||||
border-bottom: solid 1px #40404088;
|
||||
|
||||
a {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: #272727;
|
||||
}
|
||||
|
||||
span {
|
||||
background-color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.post-menu {
|
||||
.post-menu-title {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.post-menu-content {
|
||||
ul {
|
||||
border-left: 1px solid #787878;
|
||||
|
||||
.active {
|
||||
background-color: #2d2d2d;
|
||||
border-left: 2px solid #aaa;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue