all repos — nirvash @ 0d732aa7d8cbdd84258b3f17fd816c275c930625

modular CMS using the quartzgun library

implement theme support equivalent to felt
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE-----

iHUEABYKAB0WIQT/foVVmI9pK13hPWFohAcXSWbK8wUCZffOoAAKCRBohAcXSWbK
861iAP9ccxv8SGR/6knU6m7gvh/3nmZfrVZkVdoZ7pHjDLzNagEAtD90CeJnvG0g
s4Bk95ldz8FFvU6sBFXAw10VxlaftwU=
=cdEQ
-----END PGP SIGNATURE-----
commit

0d732aa7d8cbdd84258b3f17fd816c275c930625

parent

1d743646c591832497f1bf897545cd154f67279a

5 files changed, 278 insertions(+), 41 deletions(-)

jump to
M static/style.cssstatic/style.css

@@ -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 { padding: 0; margin: 0; font-family: sans-serif; font-size: 16px; - background: black; - color: white; + background: var(--bg_color); + color: var(--fg_color); background: url('/static/bg2.png'); background-size: cover; background-position: top left;

@@ -27,14 +42,14 @@ height: auto;

top: 50%; transform: translateY(-50%); -webkit-transform: translateY(-50%); - background-color: rgba(0,0,0,0.8); + background-color: var(--bg_color); padding: 1em; } .login h1 { font-size: 225%; text-transform: uppercase; - color: lightgray; + color: var(--fg_color); } .login label {

@@ -53,10 +68,10 @@ display: block;

margin-top: 0.25em; margin-left: auto; margin-right: auto; - background: rgba(0,0,0,0); - border: solid 2px lightgray; + background: var(--sub_color); + border: solid 2px var(--fg_color); font-size: 200%; - color: lightgray; + color: var(--fg_color); padding: 0.2em; max-width: calc(100vw - 2em); }

@@ -67,7 +82,7 @@ outline: none;

} .login form input:focus { - border: solid 2px cyan; + border: solid 2px var(--main_color); outline: none; }

@@ -78,8 +93,8 @@ transition: background 1s, color 1s;

} .login form input[type="submit"]:hover { - background: lightgray; - color: black; + background: var(--fg_color); + color: var(--bg_color); } .login .error {

@@ -87,8 +102,8 @@ position: relative;

text-align: center; margin-left: auto; margin-right: auto; - color: lightgray; - border-bottom: 2px solid crimson; + color: var(--fg_color); + border-bottom: 2px solid var(--err_color); width: auto; }

@@ -96,19 +111,19 @@ h1 {

text-align: center; font-size: 225%; text-transform: uppercase; - background: rgba(0,0,0,0.8); + background: var(--bg_color); margin: 0; padding-top: 0.5em; padding-bottom: 0.5em; } .login h1 { - background: rgba(0,0,0,0); + background: var(--sub_color); } nav { text-align: center; - background: rgba(0,0,0,0.8); + background: var(--bg_color); padding-top: 0.5em; padding-bottom: 0.5em; position: sticky;

@@ -128,13 +143,13 @@ margin-right: 0.5em;

} a { - color: white; + color: var(--fg_color); font-weight: normal; text-decoration: underline; } a:hover { - color: cyan; + color: var(--main_color); } .new-page-button-wrapper {

@@ -155,11 +170,11 @@ .new-page-button {

position: relative; top: 1em; text-decoration: none; - background: rgba(0,0,0,0); - border: solid 2px lightgray; + background: var(--sub_color); + border: solid 2px var(--fg_color); border-radius: 0; font-size: 150%; - color: lightgray; + color: var(--fg_color); padding: 0.2em; text-transform: uppercase; transition: background 1s, color 1s;

@@ -170,27 +185,27 @@ -moz-appearance: none;

} .new-page-button:hover { - background: lightgray; - color: black; + background: var(--fg_color); + color: var(--bg_color); } h2 { margin: 1em; font-size: 200%; text-transform: uppercase; - background: rgba(0,0,0,0.8); + background: var(--bg_color); display: block; - border-left: 8px solid cyan; + border-left: 8px solid var(--main_color); padding-left: 8px; 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; overflow-x: hidden; width: 80%; max-width: 500px; - background: rgba(0,0,0,0.8); + background: var(--bg_color); padding: 2em; margin-left: auto; margin-right: auto;

@@ -202,23 +217,23 @@ min-height: 5em;

} 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 { font-size: 80%; - color: lightgray; + color: var(--fg_color); 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; margin: 0; margin-top: 0.2em; margin-bottom: 0.2em; - background: rgba(0,0,0,0); - border: solid 2px lightgray; - color: lightgray; + background: var(--sub_color); + border: solid 2px var(--fg_color); + color: var(--fg_color); padding: 0.2em; transition: border 1s; outline: none;

@@ -233,8 +248,14 @@ transition: background 1s, color 1s;

z-index: 2; } +#theme_cfg label.nohover, #theme_cfg label.nohover:hover { + border: none; + background: transparent; + color: var(--fg_color); +} + .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"] {

@@ -252,7 +273,7 @@ font-size: 150%;

} form input:focus, form textarea:focus { - border: 2px solid cyan; + border: 2px solid var(--main_color); } form.editor, .wide {

@@ -276,7 +297,7 @@ form.configurator input, form.configurator textarea {

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-right: 0; font-size: 150%;

@@ -284,14 +305,14 @@ text-transform: uppercase;

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 { - background: lightgray; - color: black; +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: var(--fg_color); + color: var(--bg_color); } .edited-time { font-size: 75%; - color: lightgray; + color: var(--fg_color); float: right; }

@@ -308,7 +329,7 @@ line-height: 2em;

} .page-list ul li span.file-nolink { - color: #7f7f7f; + color: var(--fg_color); } .left-pad-uplink {

@@ -325,7 +346,7 @@ }

.edit-error { display: block; - border-bottom: solid 2px crimson; + border-bottom: solid 2px var(--err_color); } .file-list li a {

@@ -382,3 +403,80 @@ body {

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); +}
A static/theme.js

@@ -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");
M templates/config.htmltemplates/config.html

@@ -5,6 +5,33 @@ {{ template "header" . }}

<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"> <input hidden type="text" name="csrfToken" value="{{$csrfToken}}"/> {{ range $opt, $val := $config }}
M templates/footer.htmltemplates/footer.html

@@ -1,4 +1,6 @@

{{define "footer"}} </body> + + <script src="/static/theme.js" type="text/javascript"></script> </html> {{end}}
M templates/header.htmltemplates/header.html

@@ -7,6 +7,7 @@ <meta name='description' content='Nirvash CMS'/>

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