๐ŸŽ @totallyinformation/web-components: New release, v1.5.0 and test flows

Hi all, I'm pleased to announce a new release of my web-components package.

Full demos and documentation is here:

In addition to some bug fixes, documentation improvements, and updated standard CSS, there are 2 new components that some people may enjoy!

They are currently marked as alpha quality and so will certainly continue to improve. However, I believe that they are already useful and usable.

Don't forget that you can use these not only with UIBUILDER for Node-RED but also with either of the Dashboards and with vanilla http-in/http-response nodes. Indeed, you can use them outside of Node-RED as well of course. :smiley:

<labeled-input>

Creates an accessible, labeled user input. Currently, any type allowed by the HTML <input> tag is supported (eventually some compound inputs may also be supported). The label is easily moved to above, below, left, or right of the input simply by adding the corresponding class name. It defaults to above (e.g. a vertical layout which is the most common).

As you can see, a left or right layout automatically aligns the inputs/labels. A set of CSS variables is used to allow full and easy control of the layouts.

At present, still some things you need to do for yourself like attaching change event functions but not only do these work as you would expect, there are comprehensive examples on the demo page for you to borrow. Documentation is reasonably complete as well.

<grouped-input>

The same source file also includes this supplementary component. It is designed to wrap around <labeled-input> components to group them together. There are two configurations, form and frame. These wrap your inputs in an HTML form element or an HTML frameset.



Still plenty of room for improvements and enhancements but this is something I've been meaning to work on for ages and I've certainly a need for in my own home dashboards:

Please give them a try and let me know what is missing, needs improvement or is broken. :smiley:


Some things I know that need adding:

  • The form wrapper needs some auto-submit/clear buttons
  • The button inputs should forego the label and put the text inside the button.
  • Mobile sizing breakpoints need to be added.
  • There are also a bunch of additional things in each of the documentation pages.

Now that the component library is getting a bit more mature, I will be moving to a more standard development model using a dev branch for ongoing work and retaining the main branch for released code.

6 Likes

Would it be possible to change the colour of the links. My eyes are not what they used to be and I have to get close to see the text?

Sorry, I couldn't resist and the weather was terrible today! I was going to release 1.4.1 but in the end, the updates were too big - so here is v1.5.0

Summary of changes in v1.5

  • MAJOR UPDATE - The base component has been updated to handle more uibuilder message inputs.
    You can send a msg with the msg.topic set to component-name::id to set any property or attribute of the component. This update now allows you to set classes, styles, data-attributes, and values. Any other property is added as a property of the element rather than an attribute.

  • UPDATE - labeled-input component

    • Added auto change event to send changes immediately to Node-RED via uibuilder when the input value changes. Only if uibuilder is present and the input is not inside a form. The documentation has been updated to reflect this. The returned message topic is labeled-input/change/name where name is the name of the input. The payload contains the changed value. msg._meta contains additional data that may be of use including: the previous value, id, name and type of input.
  • button-send - Add uibuilder message sending demo.

  • Start to add uibuilder-specific HTML. Commented out but making it easier to incorporate into uibuilder pages.

    • _test-template.html
    • live/button-send.html
    • live/call-out.html
    • live/collapsible-headings.html
    • live/data-list.html
    • live/h1-title.html
    • live/html-include.html
    • live/led-gauge.html
    • alpha/labeled-input.html

To use the demo/test pages with uibuilder for Node-RED, copy the whole pages folder into your uibuilder instance folder and set the node to use that folder using the advanced tab. Then uncomment the relevant lines in the HTML head section for any page you want to use and comment out the stand-alone lines.

Test page for using with UIBUILDER for Node-RED

Here is a quick test page to help people use the web-components library with UIBUILDER.

After importing, don't forget to first name the uibuilder node and deploy. Then install the components library using uibuilder's Library Manager tab. Then you can follow the readme at the top of the imported page.

[{"id":"2c47031326e8fd01","type":"tab","label":"TI WC Tests","disabled":false,"info":"Testing the TI Web Components library\r\n\r\nRead the readme first to correctly set up these\r\ntests.","env":[]},{"id":"349a99ecf4a3ad8a","type":"group","z":"2c47031326e8fd01","name":"If the data-list test page is showing. Update the first list. New HTML text content is sent first and then a new list.","style":{"fill":"#e3f3d3","fill-opacity":"0.2","label":true,"color":"#000000"},"nodes":["b6221e56cb4d6652","fd5456075222084c","625003b509fdb71d","f6378b50eef90925","f9139d2d46e53071"],"x":54,"y":519,"w":702,"h":122},{"id":"a6adf8c814ea39df","type":"group","z":"2c47031326e8fd01","name":"Core","style":{"label":true,"color":"#000000"},"nodes":["d79da848f082d821","c1c1273697d0c0d3","dc8c6e18b6b209b6","baf98201102ea713"],"x":54,"y":99,"w":552,"h":142},{"id":"5280fb631c7d3157","type":"group","z":"2c47031326e8fd01","name":"Page controls","style":{"fill":"#bfbfbf","fill-opacity":"0.35","label":true,"color":"#000000"},"nodes":["ca1fb080bf336089","f7556a7999836b28","4493aeefd709cb84","5edd6397d8c76a02"],"x":834,"y":99,"w":332,"h":162},{"id":"0958c88d9e5ba8df","type":"group","z":"2c47031326e8fd01","name":"Testing <led-gauge> (Toggle updates on the page first)","style":{"fill":"#e3f3d3","fill-opacity":"0.25","label":true,"color":"#000000"},"nodes":["411273962d195075","9bb62bc1cd7bad3c"],"x":54,"y":679,"w":682,"h":82},{"id":"be701bbd8a0980fa","type":"group","z":"2c47031326e8fd01","name":"Testing <collapsible-headings> - any content added with headings should be collapsible - content is added at the top of the page","style":{"fill":"#e3f3d3","fill-opacity":"0.26","label":true,"color":"#000000"},"nodes":["473a297be9f81407","b108f5a5b6204a53","b0cdd123141f5eb7","617053f26322eea0","9396d8d9ec748531","2c9f8b6801b1efab"],"x":48,"y":799,"w":1128,"h":328},{"id":"617053f26322eea0","type":"group","z":"2c47031326e8fd01","g":"be701bbd8a0980fa","name":"Add/replace #more.manual-2 with heading and paras - using uib-tag node","style":{"fill":"#bfdbef","fill-opacity":"0.23","label":true,"color":"#0070c0"},"nodes":["13453844827fc8b3","9802142222f2ff62","1e1f465e6c58a04b"],"x":74,"y":919,"w":632,"h":82},{"id":"2c9f8b6801b1efab","type":"group","z":"2c47031326e8fd01","g":"be701bbd8a0980fa","name":"Replace #collapsible-headings-1 (\"My first heading\") with heading and paras - using uib-update node","style":{"fill":"#dbcbe7","fill-opacity":"0.32","label":true,"color":"#6f2fa0"},"nodes":["d0f33006afda148d","e2b5591574a4b793","badffe14b0166b36"],"x":74,"y":1019,"w":632,"h":82},{"id":"aa3ba2bdfe68dfdf","type":"group","z":"2c47031326e8fd01","name":"<labeled-input>: change first input's background colour and value","style":{"fill":"#e3f3d3","fill-opacity":"0.31","label":true,"color":"#000000"},"nodes":["3e4bf23522996347","64d9ee32caf6e104"],"x":54,"y":399,"w":662,"h":82},{"id":"9396d8d9ec748531","type":"junction","z":"2c47031326e8fd01","g":"be701bbd8a0980fa","x":940,"y":960,"wires":[["b0cdd123141f5eb7"]]},{"id":"c39c272bd6ec06f7","type":"junction","z":"2c47031326e8fd01","x":940,"y":1060,"wires":[["b0cdd123141f5eb7"]]},{"id":"d79da848f082d821","type":"debug","z":"2c47031326e8fd01","g":"a6adf8c814ea39df","name":"Std Output","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"","statusType":"counter","x":545,"y":140,"wires":[],"l":false},{"id":"c1c1273697d0c0d3","type":"uibuilder","z":"2c47031326e8fd01","g":"a6adf8c814ea39df","name":"components-html","topic":"","url":"components-html","okToGo":true,"fwdInMessages":false,"allowScripts":false,"allowStyles":false,"copyIndex":true,"templateFolder":"blank","extTemplate":"","showfolder":false,"reload":true,"sourceFolder":"tests","deployedVersion":"5.0.0-dev.2","showMsgUib":false,"title":"Testing TotallyInformation web components","descr":"","editurl":"vscode://file/src/uibRoot/components-html/?windowId=_blank","x":320,"y":160,"wires":[["d79da848f082d821"],["dc8c6e18b6b209b6"]]},{"id":"dc8c6e18b6b209b6","type":"debug","z":"2c47031326e8fd01","g":"a6adf8c814ea39df","name":"Ctrl Output","active":false,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"","statusType":"counter","x":545,"y":200,"wires":[],"l":false},{"id":"baf98201102ea713","type":"link in","z":"2c47031326e8fd01","g":"a6adf8c814ea39df","name":"link in 1","links":["5edd6397d8c76a02","b6221e56cb4d6652","9bb62bc1cd7bad3c","84a0deb0e6c3c8ca","d8f1bf63848edeca","b0cdd123141f5eb7","3e4bf23522996347"],"x":95,"y":160,"wires":[["c1c1273697d0c0d3"]]},{"id":"ca1fb080bf336089","type":"inject","z":"2c47031326e8fd01","g":"5280fb631c7d3157","name":"Toggle Visible Msgs","props":[{"p":"_uib","v":"{\"command\":\"showMsg\"}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":970,"y":140,"wires":[["5edd6397d8c76a02"]]},{"id":"f7556a7999836b28","type":"inject","z":"2c47031326e8fd01","g":"5280fb631c7d3157","name":"Log Lvl 5","props":[{"p":"_uib","v":"{\"command\":\"set\",\"prop\":\"logLevel\",\"value\":5}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1000,"y":180,"wires":[["5edd6397d8c76a02"]]},{"id":"4493aeefd709cb84","type":"inject","z":"2c47031326e8fd01","g":"5280fb631c7d3157","name":"Reload","props":[{"p":"_ui","v":"{\"method\":\"reload\"}","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"reload","x":1010,"y":220,"wires":[["5edd6397d8c76a02"]],"info":"Sends a pre-formatted msg to the front-end that\r\ncauses the page to reload itself."},{"id":"5edd6397d8c76a02","type":"link out","z":"2c47031326e8fd01","g":"5280fb631c7d3157","name":"link out 55","mode":"link","links":["baf98201102ea713"],"x":1125,"y":180,"wires":[]},{"id":"b6221e56cb4d6652","type":"link out","z":"2c47031326e8fd01","g":"349a99ecf4a3ad8a","name":"link out 56","mode":"link","links":["baf98201102ea713"],"x":715,"y":560,"wires":[]},{"id":"fd5456075222084c","type":"inject","z":"2c47031326e8fd01","g":"349a99ecf4a3ad8a","name":"data-list:","props":[{"p":"str","v":"$formatNumber($random()*100, \"0.0\")\t\t","vt":"jsonata"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":160,"y":560,"wires":[["625003b509fdb71d","f9139d2d46e53071"]]},{"id":"625003b509fdb71d","type":"uib-update","z":"2c47031326e8fd01","g":"349a99ecf4a3ad8a","name":"Change dl1 text","topic":"","mode":"update","modeSourceType":"update","cssSelector":"#dl1","cssSelectorType":"str","slotSourceProp":"<p>List is replaced by a message from Node-RED.</p>","slotSourcePropType":"str","attribsSource":"","attribsSourceType":"msg","slotPropMarkdown":false,"x":360,"y":560,"wires":[["b6221e56cb4d6652"]]},{"id":"f6378b50eef90925","type":"change","z":"2c47031326e8fd01","g":"349a99ecf4a3ad8a","name":"Change dl1 list","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"keyvalueseparator\":\" ๐Ÿ’  \",\"liststyle\":\"'๐Ÿ˜Ž '\",\"data\":{\"xxx\":\"Triple x\",\"yyy\":\"Triple y\",\"zzz\":\"triple z\"},\"style\":\"background-color: var(--surface4);\"}","tot":"json"},{"t":"set","p":"topic","pt":"msg","to":"data-list::dl1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":600,"wires":[["b6221e56cb4d6652"]]},{"id":"f9139d2d46e53071","type":"delay","z":"2c47031326e8fd01","g":"349a99ecf4a3ad8a","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":380,"y":600,"wires":[["f6378b50eef90925"]]},{"id":"e098e4cc596316be","type":"comment","z":"2c47031326e8fd01","name":"NOTE: Many of the component web pages have delayed actions in front-end code. \\n You may need to give them a few seconds before sending dynamic updates from Node-RED to avoid clashes.","info":"","x":430,"y":300,"wires":[]},{"id":"baa286f94c606dab","type":"comment","z":"2c47031326e8fd01","name":"Web components home page: https://wc.totallyinformation.net/ \\n Readme first","info":"[Web components home page](https://wc.totallyinformation.net/)\n\nCopy the `tests` folder from the\n`@totallyinformation/web-components` package.\n\nThen make sure that the delivery folder (on\nthe advanced tab) is set to use the `tests`\nfolder.\n\nFor each page, you will need to uncomment\nthe uibuilder links. You can leave the\noriginal links in place if you want since they\nsimply will fail to load.\n\nThe head section contains the `<script>` tags\nthat load the libraries. For use with uibuilder\nthey should look something like this:\n\n```html\n<!-- For stand-alone use -->\n<!-- <script defer src=\"../../dist/call-out.iife.min.js\"></script>\n<script defer src=\"../../dist/alpha/labeled-input.iife.min.js\">/* NB: Loads <labeled-input> AND <input-group> */</script> -->\n<!-- For uibuilder use -->\n<script defer src=\"../../../uibuilder/uibuilder.iife.min.js\">/* THE UIBUILDER LIBRARY MUST BE IN THE HTML! DO NOT REMOVE */</script>\n<script defer src=\"../../../uibuilder/vendor/@totallyinformation/web-components/dist/call-out.iife.min.js\"></script>\n<script defer src=\"../../../uibuilder/vendor/@totallyinformation/web-components/dist/labeled-input.iife.min.js\"></script>\n<!-- <script defer src=\"./index.js\">/* OPTIONAL: Put your custom code in that */</script> -->\n```\n\nOther links, with the exception of the documentation\nlinks should work fine.","x":280,"y":40,"wires":[]},{"id":"42a730fdc388dcbf","type":"comment","z":"2c47031326e8fd01","name":"Example updated: 2025-09-20 \\n Requires a minimum of v1.4.1 of the component package. \\n Tested using UIBUILDER v7.5.0","info":"","x":830,"y":40,"wires":[]},{"id":"411273962d195075","type":"inject","z":"2c47031326e8fd01","g":"0958c88d9e5ba8df","name":"led-gauge::led-gauge-1 - set to value 65, set colour breaks at 60 and 80","props":[{"p":"topic","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"led-gauge::led-gauge-1","payload":"{\"value\":65,\"colors\":{\"60\":40,\"80\":0}}","payloadType":"json","x":350,"y":720,"wires":[["9bb62bc1cd7bad3c"]]},{"id":"9bb62bc1cd7bad3c","type":"link out","z":"2c47031326e8fd01","g":"0958c88d9e5ba8df","name":"link out 10","mode":"link","links":["baf98201102ea713"],"x":695,"y":720,"wires":[]},{"id":"473a297be9f81407","type":"inject","z":"2c47031326e8fd01","g":"be701bbd8a0980fa","name":"Check if Markdown-IT loaded? (payload should be true)","props":[{"p":"_uib","v":"{\"command\":\"get\",\"prop\":\"markdown\"}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":300,"y":840,"wires":[["b0cdd123141f5eb7"]]},{"id":"b108f5a5b6204a53","type":"inject","z":"2c47031326e8fd01","g":"be701bbd8a0980fa","name":"Replace #more div with Markdown Content - heading, para and list - heading should be collapsable - using uibuilder low-code","props":[{"p":"_ui","v":"[{\"method\":\"replace\",\"components\":[{\"type\":\"collapsible-headings\",\"id\":\"md\",\"parent\":\"#more\",\"attributes\":{},\"slotMarkdown\":\"## H2 - Markdown input\\n\\nSome text in a para\\n\\n* List #1\\n* List #2\\n\"}]}]","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":520,"y":880,"wires":[["b0cdd123141f5eb7"]]},{"id":"b0cdd123141f5eb7","type":"link out","z":"2c47031326e8fd01","g":"be701bbd8a0980fa","name":"link out 5","mode":"link","links":["baf98201102ea713"],"x":1135,"y":840,"wires":[]},{"id":"1e1f465e6c58a04b","type":"uib-tag","z":"2c47031326e8fd01","g":"617053f26322eea0","name":"","topic":"","tag":"collapsible-headings","tagSource":"","tagSourceType":"str","parent":"#more","parentSource":"","parentSourceType":"str","elementId":"manual-2","elementIdSourceType":"str","position":"last","positionSourceType":"str","slotSourceProp":"payload","slotSourcePropType":"msg","attribsSource":"","attribsSourceType":"msg","slotPropMarkdown":false,"x":530,"y":960,"wires":[["9396d8d9ec748531"]]},{"id":"13453844827fc8b3","type":"inject","z":"2c47031326e8fd01","g":"617053f26322eea0","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"auto-create-html-from-html","payload":"{\t    \"mystring\": \"Boo-hoo\",\t    \"mynumber\": $formatInteger($random() * 100, \"#00\")\t}\t    ","payloadType":"jsonata","x":170,"y":960,"wires":[["9802142222f2ff62"]]},{"id":"9802142222f2ff62","type":"template","z":"2c47031326e8fd01","g":"617053f26322eea0","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<div style=\"border: 1px solid hsl(315deg 30% 35%)\">\n    <h2>My Dynamic Heading (h2)</h2>\n    <p style=\"background-color: hsl(315deg 30% 35%)\">\n        Added using uibuilder's <code>uib-tag</code>\n        node from a node-red HMTL template.\n    </p>\n    <p>\n        Lorem ipsum dolor sit amet, consectetur\n        adipiscing elit, sed do eiusmod tempor\n        incididunt ut labore et dolore magna aliqua.\n        Ut enim ad minim veniam, quis nostrud\n        exercitation ullamco laboris nisi ut\n        aliquip ex ea commodo consequat. Duis\n        aute irure dolor in reprehenderit in\n        voluptate velit esse cillum dolore eu\n        fugiat nulla pariatur. Excepteur sint\n        occaecat cupidatat non proident, sunt\n        in culpa qui officia deserunt mollit anim\n        id est laborum.\n    </p>\n</div>","output":"str","x":300,"y":960,"wires":[["1e1f465e6c58a04b"]]},{"id":"d0f33006afda148d","type":"inject","z":"2c47031326e8fd01","g":"2c9f8b6801b1efab","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"auto-create-html-from-html","payload":"{\t    \"mystring\": \"Boo-hoo\",\t    \"mynumber\": $formatInteger($random() * 100, \"#00\")\t}\t    ","payloadType":"jsonata","x":170,"y":1060,"wires":[["e2b5591574a4b793"]]},{"id":"e2b5591574a4b793","type":"template","z":"2c47031326e8fd01","g":"2c9f8b6801b1efab","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<div style=\"border: 1px solid hsl(165deg 30% 35%)\">\n    <h2>My Dynamic Heading (h2)</h2>\n    <p style=\"background-color: hsl(165deg 30% 35%)\">\n        Replaced the previous \"My first heading\"\n        and following paragraphs by using uibuilder's\n        <code>uib-update</code>\n        node from a node-red HMTL template.\n    </p>\n    <p>\n        Lorem ipsum dolor sit amet, consectetur\n        adipiscing elit, sed do eiusmod tempor\n        incididunt ut labore et dolore magna aliqua.\n        Ut enim ad minim veniam, quis nostrud\n        exercitation ullamco laboris nisi ut\n        aliquip ex ea commodo consequat. Duis\n        aute irure dolor in reprehenderit in\n        voluptate velit esse cillum dolore eu\n        fugiat nulla pariatur. Excepteur sint\n        occaecat cupidatat non proident, sunt\n        in culpa qui officia deserunt mollit anim\n        id est laborum.\n    </p>\n</div>","output":"str","x":300,"y":1060,"wires":[["badffe14b0166b36"]]},{"id":"badffe14b0166b36","type":"uib-update","z":"2c47031326e8fd01","g":"2c9f8b6801b1efab","name":"","topic":"","mode":"update","modeSourceType":"update","cssSelector":"#collapsible-headings-1","cssSelectorType":"str","slotSourceProp":"payload","slotSourcePropType":"msg","attribsSource":"","attribsSourceType":"msg","slotPropMarkdown":false,"x":510,"y":1060,"wires":[["c39c272bd6ec06f7"]]},{"id":"64d9ee32caf6e104","type":"inject","z":"2c47031326e8fd01","g":"aa3ba2bdfe68dfdf","name":"labeled-input:wc01","props":[{"p":"topic","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"labeled-input::wc01","payload":"{\t    \"style\": \"background-color: hsl(\" & $floor($random() * 360) & \"deg 200% 10%)\",\t    \"value\": $floor($random() * 100),\t    \"class\": \"cool cow\",\t    \"data-something\": $floor($random() * 1000)\t}","payloadType":"jsonata","x":190,"y":440,"wires":[["3e4bf23522996347"]]},{"id":"3e4bf23522996347","type":"link out","z":"2c47031326e8fd01","g":"aa3ba2bdfe68dfdf","name":"link out 6","mode":"link","links":["baf98201102ea713"],"x":675,"y":440,"wires":[]},{"id":"469767cd1c09f5df","type":"global-config","env":[],"modules":{"node-red-contrib-uibuilder":"7.5.0"}}]

The head section of each test page contains the <script> tags that load the libraries. For use with uibuilder they should look something like this:

<!-- For stand-alone use -->
<!-- <script defer src="../../dist/call-out.iife.min.js"></script>
<script defer src="../../dist/alpha/labeled-input.iife.min.js">/* NB: Loads <labeled-input> AND <input-group> */</script> -->
<!-- For uibuilder use -->
<script defer src="../../../uibuilder/uibuilder.iife.min.js">/* THE UIBUILDER LIBRARY MUST BE IN THE HTML! DO NOT REMOVE */</script>
<script defer src="../../../uibuilder/vendor/@totallyinformation/web-components/dist/call-out.iife.min.js"></script>
<script defer src="../../../uibuilder/vendor/@totallyinformation/web-components/dist/labeled-input.iife.min.js"></script>
<!-- <script defer src="./index.js">/* OPTIONAL: Put your custom code in that */</script> -->

Other links, with the exception of the documentation links should work fine.

1 Like

Hi there, hmm, those do look bad! But that isn't how they look on my system:

What browser are you using?

I deliberately don't touch the colour of links in my CSS so that you can set them at the browser. However, perhaps I should set them?

I will add a CSS variable perhaps with the default being to use the browser's choice. But then you will be able to easily override it. For the live website, I will tweak the link colours shortly since that is forced into dark mode.

@Buckskin - try the live wc.totallyinformation.net site now. I've updated the styles.

Thank you. Much better (although I am not a big fan of pink / purple :grin:). I am using Edge.

Quick look at some of the pre-alpha. What about hotNipi's edge meter would that not be a better option Gauge's for Dashboard 2.0 made with ui_template - Dashboard - Node-RED Forum. I know it is designed for dashboard v2 but it may be an easier starting place than chatGPT

I'm always open to better suggestions. :wink:

I intend to add hotnipi's gauge at some point since the component version of that that was gifted to the community by him. Happy to add the edge meter as well. Though at least the led-gauge is reasonable start I think.

There are so many things I'd like to add, but of course, each takes time which currently is in fairly short supply. However, by the end of Jan next year, I'll effectively be retired so should have more time to spend. I need to balance the time between the components and uibuilder of course though. :smiley:

Contributions from others are also always welcome and this is much easier with the components since I now include a script that templates he creation of a new component along with matching documentation and demo/test page. So over the last day or so, I've managed to add the two new components complete with demo page and documentation.