implement theme support equivalent to felt

This commit is contained in:
Iris Lightshard 2024-03-17 23:18:24 -06:00
parent 1d743646c5
commit 0d732aa7d8
Signed by: Iris Lightshard
GPG key ID: 688407174966CAF3
5 changed files with 278 additions and 41 deletions

View file

@ -1,10 +1,25 @@
:root {
--bg_color: #000000cc;
--fg_color: #fff;
--main_color: #1f9b92;
--sub_color: #00000000;
--err_color: #DC143C;
}
* { scrollbar-color:var(--main_color) var(--sub_color); }
*::-webkit-scrollbar { width:6px;height:6px; }
*::-webkit-scrollbar-track { background: var(--sub_color);}
*::-webkit-scrollbar-thumb { background:var(--main_color);border-radius:0;border:none; }
*::-webkit-scrollbar-corner { background:var(--sub_color); }
*::selection { background-color:var(--main_color);color:var(--bg_color);text-decoration:none;text-shadow:none; }
body { body {
padding: 0; padding: 0;
margin: 0; margin: 0;
font-family: sans-serif; font-family: sans-serif;
font-size: 16px; font-size: 16px;
background: black; background: var(--bg_color);
color: white; color: var(--fg_color);
background: url('/static/bg2.png'); background: url('/static/bg2.png');
background-size: cover; background-size: cover;
background-position: top left; background-position: top left;
@ -27,14 +42,14 @@ body {
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
-webkit-transform: translateY(-50%); -webkit-transform: translateY(-50%);
background-color: rgba(0,0,0,0.8); background-color: var(--bg_color);
padding: 1em; padding: 1em;
} }
.login h1 { .login h1 {
font-size: 225%; font-size: 225%;
text-transform: uppercase; text-transform: uppercase;
color: lightgray; color: var(--fg_color);
} }
.login label { .login label {
@ -53,10 +68,10 @@ body {
margin-top: 0.25em; margin-top: 0.25em;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
background: rgba(0,0,0,0); background: var(--sub_color);
border: solid 2px lightgray; border: solid 2px var(--fg_color);
font-size: 200%; font-size: 200%;
color: lightgray; color: var(--fg_color);
padding: 0.2em; padding: 0.2em;
max-width: calc(100vw - 2em); max-width: calc(100vw - 2em);
} }
@ -67,7 +82,7 @@ body {
} }
.login form input:focus { .login form input:focus {
border: solid 2px cyan; border: solid 2px var(--main_color);
outline: none; outline: none;
} }
@ -78,8 +93,8 @@ body {
} }
.login form input[type="submit"]:hover { .login form input[type="submit"]:hover {
background: lightgray; background: var(--fg_color);
color: black; color: var(--bg_color);
} }
.login .error { .login .error {
@ -87,8 +102,8 @@ body {
text-align: center; text-align: center;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
color: lightgray; color: var(--fg_color);
border-bottom: 2px solid crimson; border-bottom: 2px solid var(--err_color);
width: auto; width: auto;
} }
@ -96,19 +111,19 @@ h1 {
text-align: center; text-align: center;
font-size: 225%; font-size: 225%;
text-transform: uppercase; text-transform: uppercase;
background: rgba(0,0,0,0.8); background: var(--bg_color);
margin: 0; margin: 0;
padding-top: 0.5em; padding-top: 0.5em;
padding-bottom: 0.5em; padding-bottom: 0.5em;
} }
.login h1 { .login h1 {
background: rgba(0,0,0,0); background: var(--sub_color);
} }
nav { nav {
text-align: center; text-align: center;
background: rgba(0,0,0,0.8); background: var(--bg_color);
padding-top: 0.5em; padding-top: 0.5em;
padding-bottom: 0.5em; padding-bottom: 0.5em;
position: sticky; position: sticky;
@ -128,13 +143,13 @@ nav ul li {
} }
a { a {
color: white; color: var(--fg_color);
font-weight: normal; font-weight: normal;
text-decoration: underline; text-decoration: underline;
} }
a:hover { a:hover {
color: cyan; color: var(--main_color);
} }
.new-page-button-wrapper { .new-page-button-wrapper {
@ -155,11 +170,11 @@ a:hover {
position: relative; position: relative;
top: 1em; top: 1em;
text-decoration: none; text-decoration: none;
background: rgba(0,0,0,0); background: var(--sub_color);
border: solid 2px lightgray; border: solid 2px var(--fg_color);
border-radius: 0; border-radius: 0;
font-size: 150%; font-size: 150%;
color: lightgray; color: var(--fg_color);
padding: 0.2em; padding: 0.2em;
text-transform: uppercase; text-transform: uppercase;
transition: background 1s, color 1s; transition: background 1s, color 1s;
@ -170,27 +185,27 @@ a:hover {
} }
.new-page-button:hover { .new-page-button:hover {
background: lightgray; background: var(--fg_color);
color: black; color: var(--bg_color);
} }
h2 { h2 {
margin: 1em; margin: 1em;
font-size: 200%; font-size: 200%;
text-transform: uppercase; text-transform: uppercase;
background: rgba(0,0,0,0.8); background: var(--bg_color);
display: block; display: block;
border-left: 8px solid cyan; border-left: 8px solid var(--main_color);
padding-left: 8px; padding-left: 8px;
position: relative; position: relative;
} }
.page-list, form.editor, form.build, form.configurator, span.adapter-error, span.adapter-success, .file-move, .danger-zone, .uploader, .mkdir { .page-list, form.editor, form.build, form.configurator, span.adapter-error, span.adapter-success, .file-move, .danger-zone, .uploader, .mkdir, details.ui_win {
display: block; display: block;
overflow-x: hidden; overflow-x: hidden;
width: 80%; width: 80%;
max-width: 500px; max-width: 500px;
background: rgba(0,0,0,0.8); background: var(--bg_color);
padding: 2em; padding: 2em;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
@ -202,23 +217,23 @@ h2 {
} }
span.adapter-error { span.adapter-error {
border-bottom: 2px solid crimson; border-bottom: 2px solid var(--err_color);
} }
form.editor label, form.build label, .danger-zone label, form.configurator label, form.file-move label, .mkdir label, .page-list label { form.editor label, form.build label, .danger-zone label, form.configurator label, form.file-move label, .mkdir label, .page-list label {
font-size: 80%; font-size: 80%;
color: lightgray; color: var(--fg_color);
text-transform: uppercase; text-transform: uppercase;
} }
form.editor input, form.build input, form.editor textarea, form.configurator input, form.configurator textarea, .danger-zone input[type="submit"], .file-move input[type="submit"], .uploader label, .uploader input[type="submit"], .mkdir input, .page-list input[type="text"] { form.editor input, form.build input, form.editor textarea, form.configurator input, form.configurator textarea, .danger-zone input[type="submit"], .file-move input[type="submit"], .uploader label, .uploader input[type="submit"], .mkdir input, .page-list input[type="text"], .uploader button {
display: block; display: block;
margin: 0; margin: 0;
margin-top: 0.2em; margin-top: 0.2em;
margin-bottom: 0.2em; margin-bottom: 0.2em;
background: rgba(0,0,0,0); background: var(--sub_color);
border: solid 2px lightgray; border: solid 2px var(--fg_color);
color: lightgray; color: var(--fg_color);
padding: 0.2em; padding: 0.2em;
transition: border 1s; transition: border 1s;
outline: none; outline: none;
@ -233,8 +248,14 @@ form.editor input, form.build input, form.editor textarea, form.configurator inp
z-index: 2; z-index: 2;
} }
#theme_cfg label.nohover, #theme_cfg label.nohover:hover {
border: none;
background: transparent;
color: var(--fg_color);
}
.upload-warning { .upload-warning {
border-bottom: 2px solid crimson; border-bottom: 2px solid var(--err_color);
} }
form.editor input[type="text"], form.configurator input[type="text"], form.configurator input[type="number"], form.build input[type="text"], .mkdir input[type="text"] { form.editor input[type="text"], form.configurator input[type="text"], form.configurator input[type="number"], form.build input[type="text"], .mkdir input[type="text"] {
@ -252,7 +273,7 @@ form.editor input.title-input {
} }
form input:focus, form textarea:focus { form input:focus, form textarea:focus {
border: 2px solid cyan; border: 2px solid var(--main_color);
} }
form.editor, .wide { form.editor, .wide {
@ -276,7 +297,7 @@ form.configurator input, form.configurator textarea {
font-size: 125%; font-size: 125%;
} }
form.editor input[type="submit"], form.build input[type="submit"], .danger-zone input[type="submit"], form.configurator input[type="submit"], .file-move input[type="submit"], .uploader input[type="submit"], .mkdir input[type="submit"] { form.editor input[type="submit"], form.build input[type="submit"], .danger-zone input[type="submit"], form.configurator input[type="submit"], .file-move input[type="submit"], .uploader input[type="submit"], .mkdir input[type="submit"], .uploader button {
margin-left: auto; margin-left: auto;
margin-right: 0; margin-right: 0;
font-size: 150%; font-size: 150%;
@ -284,14 +305,14 @@ form.editor input[type="submit"], form.build input[type="submit"], .danger-zone
transition: background 1s, color 1s; transition: background 1s, color 1s;
} }
form.editor input[type="submit"]:hover,form.build input[type="submit"]:hover, .danger-zone input[type="submit"]:hover, form.configurator input[type="submit"]:hover, .file-move input[type="submit"]:hover, .uploader input[type="submit"]:hover, .uploader label:hover, .mkdir input[type="submit"]:hover { form.editor input[type="submit"]:hover,form.build input[type="submit"]:hover, .danger-zone input[type="submit"]:hover, form.configurator input[type="submit"]:hover, .file-move input[type="submit"]:hover, .uploader input[type="submit"]:hover, .uploader label:hover, .mkdir input[type="submit"]:hover, .uploader button:hover{
background: lightgray; background: var(--fg_color);
color: black; color: var(--bg_color);
} }
.edited-time { .edited-time {
font-size: 75%; font-size: 75%;
color: lightgray; color: var(--fg_color);
float: right; float: right;
} }
@ -308,7 +329,7 @@ form.editor input[type="submit"]:hover,form.build input[type="submit"]:hover, .d
} }
.page-list ul li span.file-nolink { .page-list ul li span.file-nolink {
color: #7f7f7f; color: var(--fg_color);
} }
.left-pad-uplink { .left-pad-uplink {
@ -325,7 +346,7 @@ form input[readonly] {
.edit-error { .edit-error {
display: block; display: block;
border-bottom: solid 2px crimson; border-bottom: solid 2px var(--err_color);
} }
.file-list li a { .file-list li a {
@ -382,3 +403,80 @@ input[type="file"]:valid + .file-feedback::after {
font-size: 75%; font-size: 75%;
} }
} }
#theme_cfg {
display: grid;
grid-template-columns: 1fr auto;
}
input[type=range] {
-webkit-appearance: none; /* Hides the slider so that custom slider can be made */
width: 100%; /* Specific width is required for Firefox. */
background: transparent; /* Otherwise white in Chrome */
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
}
input[type=range]:focus {
outline: none; /* Removes the blue border. You should probably do some kind of focus styling for accessibility reasons though. */
}
input[type=range]::-ms-track {
width: 100%;
cursor: pointer;
/* Hides the slider so custom styles can be added */
background: transparent;
border-color: transparent;
color: transparent;
}
input[type=range]::-webkit-slider-thumb {
height: 16px;
width: 16px;
border: none;
border-radius: 0px;
background: var(--main_color);
cursor: pointer;
}
/* All the same stuff for Firefox */
input[type=range]::-moz-range-thumb {
height: 16px;
width: 16px;
border-radius: 0px;
border: none;
background: var(--main_color);
cursor: pointer;
}
/* All the same stuff for IE */
input[type=range]::-ms-thumb {
height: 16px;
width: 16px;
border-radius: 0px;
border: none;
background: var(--main_color);
cursor: pointer;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 16px;
cursor: pointer;
background: var(--sub_color);
border-radius: 0;
border: none;
border-top: solid 1px var(--fg_color);
}
input[type=range]::-moz-range-track {
background: var(--sub_color);
height: 16px;
border-top: solid 1px var(--fg_color);
}

109
static/theme.js Normal file
View file

@ -0,0 +1,109 @@
const defaultTheme = [ "#000000cc", "#ffffffff", "#1f9b92ff", "#00000000", "#DC143Cff" ];
const saveData = {
theme: defaultTheme,
loginScreen: null,
mainScreen: null
}
function $(id) {
return document.getElementById(id);
}
function loadStorage() {
savedTheme = JSON.parse(localStorage.getItem("theme"));
saveData.theme = savedTheme || defaultTheme;
}
function hexToBytes(hex) {
let bytes = [];
for (let c = 0; c < hex.length; c += 2) {
bytes.push(parseInt(hex.substr(c, 2), 16));
}
return bytes;
}
function toByte(v) {
return ('0' +
Math.min(Math.max(parseInt(v), 0), 255).toString(16)
).slice(-2);
}
function resetTheme(theme) {
try{
let bg_col = theme[0];
let fg_col = theme[1];
let main_col = theme[2];
let sub_col = theme[3];
let err_col = theme[4];
let fg_opacity = hexToBytes(fg_col.substr(7));
fg_col = fg_col.substr(0,7);
let bg_opacity = hexToBytes(bg_col.substr(7));
bg_col = bg_col.substr(0,7);
let main_opacity = hexToBytes(main_col.substr(7));
main_col = main_col.substr(0,7);
let sub_opacity = hexToBytes(sub_col.substr(7));
sub_col = sub_col.substr(0,7);
let err_opacity = hexToBytes(err_col.substr(7));
err_col = err_col.substr(0,7);
$("bg_col_input").value = bg_col;
$("bg_col_opacity").value = bg_opacity;
$("fg_col_input").value = fg_col;
$("fg_col_opacity").value = fg_opacity;
$("main_col_input").value = main_col;
$("main_col_opacity").value = main_opacity;
$("sub_col_input").value = sub_col;
$("sub_col_opacity").value = sub_opacity;
$("err_col_input").value = err_col;
$("err_col_opacity").value = err_opacity;
} catch {}
}
function setTheme() {
try {
let bg_col = $("bg_col_input").value
let bg_opacity = toByte($("bg_col_opacity").value);
let fg_col = $("fg_col_input").value;
let fg_opacity = (toByte($("fg_col_opacity").value));
let main_col = $("main_col_input").value;
let main_opacity = (toByte($("main_col_opacity").value));
let sub_col = $("sub_col_input").value;
let sub_opacity = (toByte($("sub_col_opacity").value));
let err_col = $("err_col_input").value;
let err_opacity = (toByte($("err_col_opacity").value));
saveData.theme[0] = bg_col + bg_opacity;
saveData.theme[1] = fg_col + fg_opacity;
saveData.theme[2] = main_col + main_opacity;
saveData.theme[3] = sub_col + sub_opacity;
saveData.theme[4] = err_col + err_opacity;
localStorage.setItem("theme", JSON.stringify(saveData.theme));
} catch {} finally {
document.body.style.setProperty("--bg_color", saveData.theme[0]);
document.body.style.setProperty("--fg_color", saveData.theme[1]);
document.body.style.setProperty("--main_color", saveData.theme[2]);
document.body.style.setProperty("--sub_color", saveData.theme[3]);
document.body.style.setProperty("--err_color", saveData.theme[4]);
}
}
function setBG(screen) {
// get the input element based on screen
// create the reader
// save dataURL into localstorage
// resetBG(screen)
}
function resetBG(screen) {
// set dataURL from localstorage to theme state
// bind reader load -> body background set dataURL
}
loadStorage();
resetTheme(saveData.theme);
setTheme();
resetBG("login");
resetBG("main");

View file

@ -5,6 +5,33 @@
<h2>Configuration</h2> <h2>Configuration</h2>
<details class="ui_win uploader" id="theme_accordion"><summary>theme</summary>
<form id="theme_cfg" onsubmit="return false">
<label class="nohover">bg color<input type="color" id="bg_col_input"/></label>
<label class="nohover">bg opacity<input type="range" id="bg_col_opacity" min="0" max="255"/></label>
<label class="nohover">fg color<input type="color" id="fg_col_input"/></label>
<label class="nohover">fg opacity<input type="range" id="fg_col_opacity" min="0" max="255"/></label>
<label class="nohover">main color<input type="color" id="main_col_input"/></label>
<label class="nohover">main opacity<input type="range" id="main_col_opacity" min="0" max="255"/></label>
<label class="nohover">sub color<input type="color" id="sub_col_input"/></label>
<label class="nohover">sub opacity<input type="range" id="sub_col_opacity" min="0" max="255"/></label>
<label class="nohover">error color<input type="color" id="err_col_input"/></label>
<label class="nohover">error opacity<input type="range" id="err_col_opacity" min="0" max="255"/></label>
<div class="upload-wrapper">
<label for="login-upload">Set Login BG</label><br/>
<input type="file" id="login_bg_upload" name="file"/>
</div>
<div class="upload-wrapper">
<label for="main-upload">Set Main BG</label><br/>
<input type="file" id="main_bg_upload" name="file"/>
</div>
<button onclick="setTheme()">Apply</button><button onclick="resetTheme(defaultTheme)">Reset</button>
</form>
</details>
<form class="configurator" method="POST" action="/config-set"> <form class="configurator" method="POST" action="/config-set">
<input hidden type="text" name="csrfToken" value="{{$csrfToken}}"/> <input hidden type="text" name="csrfToken" value="{{$csrfToken}}"/>
{{ range $opt, $val := $config }} {{ range $opt, $val := $config }}

View file

@ -1,4 +1,6 @@
{{define "footer"}} {{define "footer"}}
</body> </body>
<script src="/static/theme.js" type="text/javascript"></script>
</html> </html>
{{end}} {{end}}

View file

@ -7,6 +7,7 @@
<meta name='viewport' content='width=device-width,initial-scale=1'> <meta name='viewport' content='width=device-width,initial-scale=1'>
<link rel='stylesheet' type='text/css' href='/static/style.css'> <link rel='stylesheet' type='text/css' href='/static/style.css'>
<link rel='shortcut icon' href='/static/favicon.png'> <link rel='shortcut icon' href='/static/favicon.png'>
<title>Nirvash &mdash; CMS</title> <title>Nirvash &mdash; CMS</title>
</head> </head>
<body> <body>