That heavily bended level got some improvements so you can:
change size of it just by configuring one number
adjusting led count does not break whole thing
there was more but I didn't kept the diary
So it is easier to use, (until we get the proper thing)
[{"id":"9f3c815ec5f4ba93","type":"ui-template","z":"4eb808f5e19fb7e2","group":"5d78082af21e201d","page":"","ui":"","name":"Round Led Gauge","order":7,"width":"2","height":"2","head":"","format":"<template>\n <div class=\"round-led-level\" :style=\"`--dot-count:${count}; --size:${size}; --ledsize:${ledSize};`\" >\n <header>\n <div class=\"round-led-level-text\">\n <span class=\"round-led-level-label\">{{label}}</span>\n </div>\n </header>\n <div>\n <div class=\"round-led-level-stripe\">\n <div v-for=\"(color, index) in colors\" :key=\"index\" class=\"round-led-level-led\" :ref=\"'dot-' + index +'-'+this.id\">\n </div>\n </div>\n <div class=\"round-led-level-centered-text\">\n <span class=\"round-led-level-value\">{{formattedValue}}</span>\n <span class=\"round-led-level-unit\">{{unit}}</span>\n </div>\n <div class=\"round-led-level-limits\">\n <span>{{min}}</span>\n <span>{{max}}</span>\n </div>\n </div> \n <div>\n</template>\n\n<script>\nexport default {\n data(){\n return {\n //define me here\n label:\"MEASURE\", // the label\n min:0, //smallest expected value\n max:100, //higest expected value\n unit:\"cmĀ³\",// unit of the measurement\n size:140, // ovaerall size. (think in pixels) under 100 will be too small. \n animate:true,// animating leds is not most performant thing in the world. \n dark:0.4, // how dim is led when not glowing \n //define colors as you wish but the thing works clockwise.\n //led size depends on how many colors is defined. \n colors:[ \n \"rgb(var(--v-theme-primary))\",\n \"rgb(var(--v-theme-primary))\",\n \"rgb(var(--v-theme-primary))\",\n \"rgb(var(--v-theme-primary))\",\n \"rgb(var(--v-theme-primary))\",\n \"rgb(var(--v-theme-primary))\",\n \"rgb(var(--v-theme-primary))\",\n \"rgb(var(--v-theme-primary))\",\n \"rgb(var(--v-theme-primary))\",\n \"rgb(var(--v-theme-primary))\",\n \"rgb(var(--v-theme-warning))\",\n \"rgb(var(--v-theme-warning))\",\n \"rgb(var(--v-theme-warning))\",\n \"rgb(var(--v-theme-error))\",\n \"rgb(var(--v-theme-error))\",\n ], \n //no need to change those\n value:0,\n previousValue:0,\n inited:false\n }\n },\n\n \n methods: { \n getElement: function(name,base){\n if(base){\n return this.$refs[name]\n }\n return this.$refs[name][0]\n },\n\n full: function(){\n return Math.floor(this.colors.length*this.percentage/100)\n },\n half: function (){\n let p = this.colors.length*this.percentage/100;\n p -= this.full()\n p *= .5\n p += this.dark;\n return p;\n },\n\n lit: function(){\n if(this.inited == false){\n return\n }\n const down = this.previousValue > this.value\n\n let time = .01\n this.colors.forEach((e,i) => {\n let dot = this.getElement(\"dot-\"+i+\"-\"+this.id);\n if(!dot){\n console.log(\"no dots found\")\n return\n } \n if(i<this.full()){\n dot.style.filter= \"brightness(1.1)\";\n }\n else if(i==this.full()){ \n dot.style.filter = \"brightness(\"+this.half()+\")\";\n }\n else{\n dot.style.filter= \"brightness(\"+this.dark+\")\";\n }\n if(down){\n time = (this.colors.length - i) * .12 \n }\n dot.style.transition = this.animate ? \"filter \"+time+\"s\" : \"unset\";\n })\n this.previousValue = this.value\n }\n },\n watch: {\n msg: function(){ \n if(this.msg.payload != undefined){ \n this.value = this.msg.payload \n this.lit()\n }\n }\n },\n computed: {\n formattedValue: function () {\n return this.value.toFixed(2)\n },\n percentage: function(){\n return Math.floor(((this.value - this.min) / (this.max - this.min)) * 100);\n },\n count: function() {\n return this.colors.length;\n }, \n ledSize:function(){\n const s = 4.71239 * ((this.size - (this.size*0.3))/2) \n return s / this.colors.length\n }\n },\n mounted(){\n let angle;\n const step = 270 / this.colors.length; //this.ledSize/2;//270 / (this.colors.length + 2);\n const radius = (this.size - (this.size*0.1))/2//this.size / 2;\n const s = this.ledSize / -2; \n this.colors.forEach((c,i) => {\n let dot = this.getElement(\"dot-\"+i+\"-\"+this.id);\n if(!dot){\n console.log(\"no dots found\")\n return\n }\n dot.style.backgroundColor = c \n dot.style.transition = \"filter 0.1s\";\n dot.style.setProperty('--dot',i);\n angle = ((i+1)*step) * Math.PI / 180;\n dot.style.left = s + radius * Math.cos(angle) + 'px';\n dot.style.top = s + radius * Math.sin(angle) + 'px';\n dot.style.transform = 'translate('+s+'px, '+s+'px)'; \n dot.style.rotate = (angle - 0.08)+\"rad\" \n }\n )\n \n this.inited = true;\n },\n \n}\n</script>\n","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":630,"y":360,"wires":[[]]},{"id":"2545d92a227a8572","type":"ui-template","z":"4eb808f5e19fb7e2","group":"","page":"","ui":"da26eafa8eb48ab3","name":"Round Led Gauge for Dasboard 2.0 CSS","order":0,"width":0,"height":0,"head":"","format":".round-led-level{\n display: grid;\n grid-template-rows: 1em 1fr;\n height: calc(var(--size) * 1px);\n aspect-ratio: 1/1;\n position: relative;\n margin: auto;\n}\n.round-led-level>div{\n position: relative;;\n}\n.round-led-level-stripe{\n display: block;\n position: absolute;\n left: 50%;\n top: 56%;\n rotate: 135deg; \n} \n.round-led-level-led {\n background: #ffffff;\n position: absolute;\n width: calc(var(--ledsize) * 1px);\n aspect-ratio: 1/1;\n border-radius: 4px;\n box-shadow: inset 0px 0px calc(var(--ledsize) / 3 * 1px) 0px #00000099, 0px 0px calc(var(--ledsize) / 7 * 1px) 0px #00000099;\n filter: brightness(0.4);\n transform-origin: center center;\n \n\n}\n.round-led-level-text{ \n font-size: 1rem;\n line-height: 1rem;\n text-align: center;\n user-select: none;\n}\n.round-led-level-centered-text{\n position: absolute;\n inset: 0;\n font-size: 1rem;\n line-height: 1;\n display: grid;\n text-align: center;\n grid-template-rows: 1fr 1fr;\n gap: .25em;\n user-select: none;\n padding-block: 42%;\n align-items: center;\n}\n.round-led-level-value{ \n font-weight:bold;\n font-size: calc(var(--size) * .15 * 1px);\n}\n.round-led-level-unit{\n font-size:calc(var(--size) * .1 * 1px);\n font-weight:normal;\n padding-inline-start: 0.15em;\n}\n.round-led-level-limits{\n position: absolute;\n inset:0; \n display: flex;\n justify-content: space-between;\n font-size: calc(var(--size) * .06 * 1px);\n line-height: calc(var(--size) * .06 * 1px);\n align-content: flex-end;\n flex-wrap: wrap;\n padding-inline:1em;\n user-select: none;\n}","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"site:style","className":"","x":700,"y":320,"wires":[[]]},{"id":"5d78082af21e201d","type":"ui-group","name":"Some stuff","page":"71097e9858ab99f9","width":"6","height":"1","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"da26eafa8eb48ab3","type":"ui-base","name":"Board","path":"/dashboard"},{"id":"71097e9858ab99f9","type":"ui-page","name":"Test page","ui":"da26eafa8eb48ab3","path":"/second","icon":"home","layout":"grid","theme":"a965ccfef139317a","order":-1,"className":"","visible":"true","disabled":"false"},{"id":"a965ccfef139317a","type":"ui-theme","name":"Default","colors":{"surface":"#575757","primary":"#0fb8ad","bgPage":"#474747","groupBg":"#525252","groupOutline":"#7c837e"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]
And with that I'm going to shut up in terms of indicator widget prototypes and let the thread to be Dashboard 2.0 again
Don't even know what do now ...