ctucx.git: mqtt-webui

webui for mqtt, can be used to control/display data in mqtt-topics

commit 10e3cb5b813fff816227441840b4d9919db16d7c
parent b66ee64102d4d8ec0836ae3a7f5d7189776849ce
Author: Leah (ctucx) <git@ctu.cx>
Date: Mon, 12 Dec 2022 13:40:23 +0100

improve css
5 files changed, 109 insertions(+), 53 deletions(-)
M
src/webui.css
|
112
++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
M
src/webui.js
|
20
++++++++++++++++----
M
www/index.html
|
26
++++++++++++++++++++++++++
M
www/manifest.json
|
2
--
M
www/sw.js
|
2
+-
diff --git a/src/webui.css b/src/webui.css
@@ -1,5 +1,20 @@
+@media screen {
+	:root {
+		--background-color:                #f8f9fa;
+		--nav-background-color:            rgba(248, 249, 250, 0.3);
+		--nav-scroll-border-color:         rgba(0, 0, 0, 0.125);
+		--section-header-background-color: #f8f9fa;
+		--section-border-color:            rgba(0, 0, 0, 0.125);
+		--text-color:                      #212529;
+		--icon-color:                      #212529;
+		--toggle-background-color:         #ccc;
+		--toggle-knob-color:               #6c757d;
+		--toggle-knob-active-color:        #693;
+	}
+}
+
 *, ::before, ::after {
-  box-sizing: border-box;
+	box-sizing: border-box;
 }
 
 body {

@@ -8,14 +23,14 @@ body {
 	font-size: 1rem;
 	font-weight: 400;
 	line-height: 1.5;
-	color: #212529;
+	color: var(--text-color);
 	text-align: left;
-	background-color: #f8f9fa;
-	padding-top: 66px;
+	background-color: var(--background-color) !important;
+	padding-top: 70px;
 }
 
 a {
-	color: #212529;
+	color: var(--text-color);
 	text-decoration: none;
 }
 

@@ -28,25 +43,34 @@ img {
 }
 
 nav {
-	margin-left: auto;
-	margin-right: auto;
-	max-width: 50em;
-	background-color: #f8f9fa;
+	background-color: var(--nav-background-color);
+	-webkit-backdrop-filter: blur(3rem);
+	backdrop-filter: blur(3rem);
 	position: fixed;
+	z-index: 1;
 	top: 0;
 	left: 0;
 	right: 0;
 	padding: .5rem 1rem;
+}
+
+header {
+	margin-left: auto;
+	margin-right: auto;
+	max-width: 50em;
 	align-items: center;
 	display: flex;
 	flex-wrap: wrap;
 	justify-content: space-between;
 }
 
+.scroll {
+	border-bottom: 1px solid var(--nav-scroll-border-color);
+}
+
 nav a {
 	padding-top: 0.3125rem;
 	padding-bottom: 0.3125rem;
-	margin-right: 1rem;
 	font-size: 1.25rem;
 	white-space: nowrap;
 }

@@ -67,18 +91,17 @@ button .icon {
 	padding: 0 .3rem;
 }
 
-button .icon svg {
-	color: #212529;
+.icon {
 	height: 31px;
 	width: 31px;
-}
-
-.icon {
-	height: 32px;
-	width: 32px;
 	margin: 4px;
 }
 
+.icon svg {
+	color: var(--icon-color);
+	height: 31px;
+	width: 31px;
+}
 
 .page {
  	margin-left: auto;

@@ -88,20 +111,20 @@ button .icon svg {
 
 section {
 	border-radius: 0.25rem;
+	border: 1px solid var(--section-border-color);
 	margin-bottom: 10px;
 }
 
 section > div {
 	background-color: #fff;
 	padding: 0.25rem;
-	border: 1px solid rgba(0, 0, 0, 0.125);
-	border-bottom: 0;
+	border-bottom: 1px solid var(--section-border-color);
 	display: flex;
 	align-self: center !important;
 }
 
 section > div:first-child {
-	background-color: #f8f9fa;
+	background-color: var(--section-header-background-color);
 	padding-left: 1em;
 	border-top-left-radius: inherit;
 	border-top-right-radius: inherit;

@@ -110,7 +133,7 @@ section > div:first-child {
 section > div:last-child {
 	border-bottom-right-radius: inherit;
 	border-bottom-left-radius: inherit;
-	border-bottom: 1px solid rgba(0, 0, 0, 0.125);
+	border-bottom: 0;
 }
 
 section > div * {

@@ -130,24 +153,11 @@ section > div .title{
 	text-overflow: ellipsis;
 }
 
-@media screen and (max-width: 700px) {
-	section {
-		border-radius: 0;
-		margin-bottom: 0px;
-	}
-
-	section > div {
-		border-bottom: 1px solid rgba(0, 0, 0, 0.125);
-		border-width: 0 0 1px;
-	}
-}
-
 
 /* Switch Styling*/
-
 .toggle {
 	font-family: sans-serif;
-	background-color: #ccc;
+	background-color: var(--toggle-background-color);
 	display: inline-block;
 	border-radius: 1.2em;
 	padding: 0.2em 2em 0.2em 0.2em;

@@ -161,7 +171,7 @@ section > div .title{
 	position: relative;
 	transition: transform 0.1s;
 	cursor: pointer;
-	background-color: #6c757d;
+	background-color: var(--toggle-knob-color);
 	color: #fff;
 	display: inline-block;
 	padding: 0.25em 1em;

@@ -169,7 +179,7 @@ section > div .title{
 }
 
 .toggle input:checked + label {
-	background-color: #693;
+	background-color: var(--toggle-knob-active-color);
 	color: #fff;
 	transform: translateX(1.8em);
 }

@@ -192,7 +202,7 @@ section > div .title{
 	border-radius: 50%; 
 	background: #6c757d;
 	cursor: pointer;
-	box-shadow:var(--c,0) 0 0 #ccc;
+	box-shadow: var(--c,0) 0 0 #ccc;
 }
 
 .slider::-moz-range-thumb {

@@ -201,7 +211,7 @@ section > div .title{
 	border-radius: 50%;
 	background: #6c757d;
 	cursor: pointer;
-	box-shadow:var(--c,0) 0 0 #ccc;
+	box-shadow: var(--c,0) 0 0 #ccc;
 }
 
 

@@ -216,11 +226,6 @@ section > div .title{
 	vertical-align: middle;
 }
 
-@keyframes spin {
-	0% { transform: rotate(0deg); }
-	100% { transform: rotate(360deg); }
-}
-
 .working {
 	background-color: lightgray;
 	animation-name: color;

@@ -228,6 +233,11 @@ section > div .title{
 	animation-iteration-count: infinite;
 }
 
+@keyframes spin {
+	0% { transform: rotate(0deg); }
+	100% { transform: rotate(360deg); }
+}
+
 @keyframes color {
   0% {
 	background-color: lightgray;

@@ -238,4 +248,15 @@ section > div .title{
   100% {
 	background-color: lightgray;
   }
-}-
\ No newline at end of file
+}
+
+@media screen and (max-width: 700px) {
+	section > div:last-child {
+		border-bottom: 1px solid var(--section-border-color);
+	}
+	section {
+		border-radius: 0;
+		border-width:  0;
+		margin-bottom: 0;
+	}
+}
diff --git a/src/webui.js b/src/webui.js
@@ -297,18 +297,29 @@ const renderPage = (pageConfig) => {
 	return  html`
 		<div id="${pageConfig.id}" class="page">
 			<nav>
-				${backButton}
-				<a href="#"><img src="${ifDefined(pageConfig.icon)}" width="30" height="30"> ${pageConfig.title}</a>
-				<button class="icon connectionStatus" @click="${() => window.location.reload(true)}">${unsafeSVG(disconnectedSvg)}</button>
+				<header>
+					${backButton}
+					<a href="#"><img src="${ifDefined(pageConfig.icon)}" width="30" height="30"> ${pageConfig.title}</a>
+					<button class="icon connectionStatus" @click="${() => window.location.reload(true)}">${unsafeSVG(disconnectedSvg)}</button>
+				</header>
 			</nav>
 			${map(pageConfig.sections, (sectionConfig) => renderSection(sectionConfig))}
 		</div>
 	`;
-};
+}
 
 const renderPages = (config) => html`${map(config.pages, (pageConfig) => renderPage(pageConfig))}`;
 
+const scrollHandler = (event) => {
+	if (window.scrollY > 0) {
+		document.querySelectorAll('nav').forEach((element) => element.classList.add('scroll'));
+	} else {
+		document.querySelectorAll('nav').forEach((element) => element.classList.remove('scroll'));
+	}
+}
+
 window.addEventListener('hashchange', goToPage);
+window.addEventListener("scroll", scrollHandler);
 window.addEventListener('DOMContentLoaded', async (event) => {
 	const instanceId = localStorage.getItem('instanceId') ?? Math.random().toString(36).slice(2);
 	const username   = localStorage.getItem('username')   ?? prompt("userame:");

@@ -340,6 +351,7 @@ window.addEventListener('DOMContentLoaded', async (event) => {
 
 	// create UI
 	render(renderPages(config), document.body);
+	document.getElementById("loading").style.display = 'none';
 	goToPage();
 
 	// MQTT
diff --git a/www/index.html b/www/index.html
@@ -10,8 +10,34 @@
 		<link rel="stylesheet" href="./bundle.css">
 		<link rel="manifest" href="./manifest.json">
 		<title>Smart-Home</title>
+		<style>
+			body {
+				background-color: #f8f9fa;
+			}
+
+			#loading {
+				position: absolute;
+				left: 0;
+				right: 0;
+				top: 0;
+				bottom: 0;
+				margin: auto;
+				border: 4px solid #ccc;
+				border-top: 4px solid #6c757d;
+				border-radius: 50%;
+				width: 32px;
+				height: 32px;
+				animation: spin 1.5s linear infinite;
+			}
+
+			@keyframes spin {
+				0% { transform: rotate(0deg); }
+				100% { transform: rotate(360deg); }
+			}
+		</style>
 	</head>
 	<body>
+		<div id="loading"></div>
 		<script src="bundle.js" type="module"></script>
 	</body>
 </html>
diff --git a/www/manifest.json b/www/manifest.json
@@ -9,7 +9,5 @@
 			"type": "image/png"
 		}
 	],
-	"theme_color": "#616161",
-	"background_color": "#ffffff",
 	"display": "standalone"
 }
diff --git a/www/sw.js b/www/sw.js
@@ -50,7 +50,7 @@ let preCache = [
 	'./icons/weather.png'
 ];
 
-const CACHE = 'cache-v2';
+const CACHE = 'cache-v4';
 
 self.addEventListener('install', function (evt) {
 	self.skipWaiting();