Dynamic Dashboard Theme

Hello all,

I have seen a few posts regarding dynamically changing the dashboard "theme" (colors). I thought it was worth an updated post as I haven't found a post discussing this dated less than a year ago. And there have been several changes to both Node-RED and the dashboard since then.

Is there a way to change the colors of the dashboard dynamically? Such as switching between a light and dark theme? I'm not comfortable enough at this point to use the ui-builder node, but I realize this could be a solution for me in the future. So I'm looking at alternative options.

I see this snippet of the official node-red-dashboard (node) page:


I realize this is to make it easier to override the css with custom css. But is there a way to use these in a ui-template node to change the colors? Then force a refresh using the ui-control node?

If this isn't possible, is there a way to change the theme from the themes setup in the "theme" menu of the editor? For example, you can set up your light, dark, and custom themes and then switch between them?

Or would switching to angular theme help with this at all? I'm assuming the reasons why this is difficult would be the same with any of the ideas I mentioned, but just thought I'd throw out some options. I would appreciate any ideas or guidance on this topic.

It is not too complicated but kind of time consuming thing to do. Depends how many different things you re using for your dashboard.

The list of css variables you mentioned is not too useful cos they are not used by dashboard widgets. This list is created just to be used when you do some widget with ui_template (or custom dashboard node) and you want to match your colors with other things in dashboard.

Overall it take to:
Understand CSS a bit,
Then understand how to find all required elements and their color properites,
then make your own rules to override defaults.
With those you define colors as css variables
and then you can make a logic where you manipulate those variables.

Thanks for the reply!

So I'm assuming I can use the inspect tool to find the elements and their color properties? I was able to manipulate the background color using the following code in a ui-template

<style>
   .nr-dashboard-theme {
      background-color: black !important;
   }
</style>

But the trouble has been setting up a ui-template to change variables on the fly. I have tried two different approaches and neither one is working.

Setting flow/global variables and then reading them in the ui-template.
Sending the payload from a switch/button into the ui-template.

Then I use something like:

<style>
   .nr-dashboard-theme {
      background-color: {{msg.payload}} !important;
   }
</style>

Am I on the right track? I have seen some code in a ui-template that uses function scope to check for an incoming payload, perhaps that's what I've been missing. Also, will the colors update once the ui-template is updated? Or will I need to trigger a refresh of the page?

Almost on right track. The thing is that you'll need to make some set ov variables which satisfy all hat dashboard needs color wise.

For that the previously mentioned list may do the trick (I never tried to make full theme override dynamically. so I dont know)

To make rules to override widget defaults, you'll need to make roules with variables for the color properties. For example the button widget it will be like this. (This is simple case. sure there may be more elements for different widgets,may be borders and so on. )

And yes, some cases you are forced to use the !Important rule to make it working.

To do dynamic change, you'll need anoter ui_template to change css variables.
It is up to you how you want that dynamics be created but the method to change the variables with JavaScript is as following:

document.documentElement.style.setProperty('--your-variable', '#YOURCOLOR');

So the template code to accept and apply changes may be something like this:

<script>
    (function(scope) {
  scope.$watch('msg', function(msg) {
    if (msg) {
      // Do something when msg arrives
      //assuming that payload contains property widgetcolor (and not only) which is color as string like "#ff00ff"
      document.documentElement.style.setProperty('--nr-dashboard-widgetColor', msg.payload.widgetcolor);
//document.documentElement.style.setProperty('--nr-some-other-color', msg.payload.that_other_color);
    }
  });
})(scope);
</script>

I attempted to get your solution to work but I must be missing something. These are my three nodes, ui-button, and two ui-templates.

[{"id":"16356421def6eecd","type":"ui_button","z":"dc5564e9aa5a8011","name":"","group":"a4bc9ae89a74a511","order":3,"width":0,"height":0,"passthru":false,"label":"button","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"#eeeeee","payloadType":"str","topic":"topic","topicType":"msg","x":680,"y":740,"wires":[["5e14acbe28ccf5de"]]},{"id":"5e14acbe28ccf5de","type":"ui_template","z":"dc5564e9aa5a8011","group":"a4bc9ae89a74a511","name":"","order":4,"width":0,"height":0,"format":"<script>\n    (function(scope) {\n  scope.$watch('msg', function(msg) {\n    if (msg) {\n      // Do something when msg arrives\n      //assuming that payload contains property widgetcolor (and not only) which is color as string like \"#ff00ff\"\n      document.documentElement.style.setProperty('--nr-dashboard-pageBackgroundColor', msg.payload);\n//document.documentElement.style.setProperty('--nr-some-other-color', msg.payload.that_other_color);\n    }\n  });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"global","className":"","x":880,"y":740,"wires":[[]]},{"id":"a6f6ebdbc0be183e","type":"ui_template","z":"dc5564e9aa5a8011","group":"a4bc9ae89a74a511","name":"","order":5,"width":0,"height":0,"format":"<style>\n\n.nr-dashboard-theme {\n    background-color: var(--nr-dashboard-pageBackgroundColor) !important;\n}\n\n</style>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"global","className":"","x":1130,"y":780,"wires":[[]]},{"id":"a4bc9ae89a74a511","type":"ui_group","name":"Title","tab":"93580c59dde9f84b","order":1,"disp":false,"width":12,"collapse":false,"className":""},{"id":"93580c59dde9f84b","type":"ui_tab","name":"LRTU Alarm Panel","icon":"dashboard","order":5,"disabled":false,"hidden":false}]

When I press the button nothing happens, if I refresh the page nothing happens. If I change the color in the ui-template that isn't connected to the button with a color (#eeeeee) then it changes as expected.

The ui_template where you apply changes must not be targeted to "site head" but must me widget in group. Also if you have multiple tabs, one such template must be on every tab. Cos if tab is not active, the ui_template just does not exist and the code cant run.

image

That was it! It is working great now.

Is there an easy way to see what the css tag names are for the items corresponding to the options in the "custom theme" section of the node red editor?

I don't know any other ways than try and explore with dev tools or inspect dashboard source code.
As told, now as you know what to do, the longest and quite boring part of work starts.

This is working well. To help anyone who may come along later, I will post some notes. This appears to work for the group and widget backgrounds, but I am not a CSS guru in the slightest.

<style>

// Groups
.nr-dashboard-cardcontainer {
    background-color: var(--nr-dashboard-pageBackgroundColor) !important;
    
}
// Widgets
.nr-dashboard-theme md-content md-card {
    background-color: var(--nr-dashboard-pageBackgroundColor) !important;
    color: black !important;
}

</style>

"background-color" is self-explanatory and "color" changes the text color. So between these I can simply change the background and text color of the groups and widgets. hotNipi has already provided an example of changing widget colors such as buttons. With more experimentation I'm sure I can find the other parameters such as Title Bar color, Group Border color, etc.

Thanks again for the help!

While not designed for Dashboard, the uib-brand.css file that comes with uibuilder has been built specifically for both auto and manual switching between light and dark. It is fully variable driven so can be easily adjusted for base hue and many other parameters.

It takes your browser preference automatically for light/dark but manual switching is as simple as adding the appropriate class to the html element. There is even an HTML component available that provides a visible adjustments form.

It would give you a head-start for the creation of a Dashboard-specific CSS.

This is good to know. So I would need to download the ui-builder node and then locate the file uibrand.css that gets created? I have no experience with the ui-builder although I've heard about it a lot.

I'm guessing this wouldn't necessarily help me find the css names for the items in the "custom theme" section? Through trial and error I've found several (at least they appear to work for what I'm wanting to do), but it would be nice to know if what I'm doing is "correct".

Not necessarily :grin:

node-red-contrib-uibuilder/uib-brand.css at main · TotallyInformation/node-red-contrib-uibuilder (github.com)

Though of course, you might find some uses for uibuilder as well. :rofl:

No, afraid not. There is no relation between Dashboard and uibuilder. But at least the CSS concepts are laid bare in my css file and there are plenty of comments. And I'm generally to be found around the forum so you can also ask questions - I might even answer them even though they might not be related to uibuilder itself. :saluting_face:

1 Like

Lol I appreciate it. I have a very basic understanding of css and I can usually brute force my way into getting the simple customization I want from the built in dashboard.

I'm planning on working my way through the w3 school css material so I can craft even more customized dashboards/ui.

I've been using the inspect tool to try to find the css names of the items in the "custom theme" so I can manipulate them dynamically. If you have any pointers, or know of any similar files to the .css file that the built in dashboard uses I'd be interested.

You can take much easier path to learn than digging in W3.

2 Likes

This looks great. Thanks for sharing!

Are there any specific playlists of his you recommend?

No cos everything is pure gold.

1 Like

There are various themes so that is a good place to start for the Dashboard side.

node-red-contrib-themes/theme-collection: A collection of themes for Node-RED (github.com)

Dashboard Theme : Modern Dark (flow) - Node-RED (nodered.org)

Compare against mine so that you start to understand how you can combine the two.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.