Custom ui node containing SVG image not sizing correctly on dashboard

I am trying to develop a D2 ui node that contains a square SVG image. The problem is that there is a large gap below the image above the next widget in the dashboard unless the widget size is configured as auto. If the widget size is configured as, for example, 4x4, then the gap is present.

I have developed a very simple test node and a flow that consists of two svg nodes with text nodes around them that shows the problem. It appears as

The upper svg node is sized auto, the lower 4x4. I don't know whether this is a dashboard issue or whether a bit of magic css will sort it, or possibly both I suppose.

If anyone already knows what the problem is then that would be great. If not then if anyone has the time to install the node and give it a go I would be most grateful. It can be installed using
npm install colinl/node-red-dashboard-2-ui-test-node
Here is the test flow

[{"id":"330777a7368c0197","type":"ui-test-node","z":"997da33a0beedade","name":"Test node auto","group":"5adfd329078662d5","order":4,"width":"0","height":"0","label":"Some label","myclass":"","x":400,"y":6440,"wires":[]},{"id":"cc6730e201cdd9bc","type":"ui-text","z":"997da33a0beedade","group":"5adfd329078662d5","order":3,"width":0,"height":0,"name":"Text above","label":"Text above auto sized svg","format":"{{msg.payload}}","layout":"row-spread","style":false,"font":"","fontSize":16,"color":"#717171","className":"","x":390,"y":6380,"wires":[]},{"id":"d7cf2326a6a5509d","type":"ui-text","z":"997da33a0beedade","group":"5adfd329078662d5","order":5,"width":0,"height":0,"name":"Text between","label":"Text between","format":"{{msg.payload}}","layout":"row-spread","style":false,"font":"","fontSize":16,"color":"#717171","className":"","x":390,"y":6500,"wires":[]},{"id":"ab2c75e1976ab0cc","type":"ui-text","z":"997da33a0beedade","group":"5adfd329078662d5","order":7,"width":0,"height":0,"name":"Text below","label":"Text below 4x4 sized svg","format":"{{msg.payload}}","layout":"row-spread","style":false,"font":"","fontSize":16,"color":"#717171","className":"","x":390,"y":6620,"wires":[]},{"id":"a840394519d151e1","type":"ui-test-node","z":"997da33a0beedade","name":"Test node 4x4","group":"5adfd329078662d5","order":6,"width":"4","height":"4","label":"Some label","myclass":"","x":400,"y":6560,"wires":[]},{"id":"5adfd329078662d5","type":"ui-group","name":"SVG test","page":"73721cb540947283","width":"5","height":"1","order":-1,"showTitle":false,"className":"","visible":"true","disabled":"false"},{"id":"73721cb540947283","type":"ui-page","name":"SVG test","ui":"ID-BASE-1","path":"/svg","icon":"home","layout":"flex","theme":"f9b6670b127dc219","order":1,"className":"","visible":"true","disabled":"false"},{"id":"ID-BASE-1","type":"ui-base","name":"Dashboard","path":"/dashboard"},{"id":"f9b6670b127dc219","type":"ui-theme","name":"FlowForge Theme","colors":{"surface":"#152a47","primary":"#005aff","bgPage":"#ffffff","groupBg":"#ffffff","groupOutline":"#cc3e3e"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]

A ui-template containing just the same SVG does not show the problem.

To remove the node again npm remove @colinl/node-red-dashboard-2-ui-test-node

What is the size of the group you're wrapping these inside? I'm guessing 6 x 1?

I'd expect the gap to the right of the SVG (given auto would make it width: 6, and you've specified width: 4, but not below it...

The group is 5 wide in fact. The top one (auto) is 5x5 as one would expect. The width of the bottom one correct (4), but the total height used is close to 6.

This might be interesting. When I inspect the element the svg div shows the correct size, but when I look at the containing widget div which is

<div id="nrdb-ui-widget-a840394519d151e1" class="nrdb-ui-widget nrdb-ui-test-node" 
style="display: grid; grid-template-rows: repeat(4, minmax(45px, auto)); 
grid-row-end: span 4; grid-column-end: span 4;">

I see this:

Could it be that SVG is going into the first row of the four, with the three remaining rows below it, instead of the SVG overlaying all four rows?

That's exactly whats happening, but the SVG element should auto fill the 4 rows given the CSS present and how we render the widgets in a layout.

I'll need to have this running locally to find out more. Great find though

I ran into this similar issue a little while ago when trying to fit a scalable video player into dashboard 2. As a test, try removing the auto (via the browser debug tools) and you will see the space seems normal. I was able to get around this with a little css that I accidentally stumbled across. Also, I had to add an extra container div. Atleast now, I have a custom element that seems to look correct on dashboard 1 and 2. I tried working with your node, but couldn't figure how to update all of that vue stuff to get the stylesheet to do anything, sorry.

Removing auto does fix it, thanks, however, I see that @BartButenaers` svg node does not have the problem so I compared the DOM for my node and his.

@joepavitt perhaps you can throw some light on this. As in the provided example node, in my vue file I have

<template>
    <!-- Component must be wrapped in a block so props such as className and style can be passed in from parent -->
    <div className="ui-test-cl-wrapper">
        <svg ....

and @BartButenaers has effectively the same. However, in my DOM this generates

<div id="nrdb-ui-widget-a840394519d151e1" class="nrdb-ui-widget nrdb-ui-test-node" style="display: grid; grid-template-rows: repeat(4, minmax(45px, auto)); grid-row-end: span 4; grid-column-end: span 4;">
<!-- Component must be wrapped in a block so props such as className and style can be passed in from parent -->
<div data-v-6e6d8067="" class="ui-test-cl-wrapper">
<svg ....

and Barts has the same, except the second div is
<div data-v-dfd731c1="" class="ui-svg-wrapper" style="grid-row-end: span 4;">
Note that it has the additional style setting that mine does not. I presume the style is passed in from the parent, as mentioned in the comment
<!-- Component must be wrapped in a block so props such as className and style can be passed in from parent -->

If I add style="grid-row-end: span 4;" into the template then that sorts the problem, but I can't see what is different between Bart's and my nodes that would explain why it is not automatically inserted into my code.

Hmm, so the purpose of auto here is to resize to the content, if the content extends beyond the 45px limit, this is particularly useful for ui-template, ui-markdown or ui-table, where the height of content can grow.

I'll dig into this in more detail today or tomorrow and trying to work out if there is a more general-purpose fix I can provide as you guys shouldn't need to be concerned with this level of CSS for a third-party node.

I seem to have found a solution. I have changed the container div from
<div className="ui-test-cl-wrapper">
to
<div className="ui-gauge-cl-wrapper" :style="wrapperStyle">
with a computed function

        wrapperStyle: function() {
            let rowSpan = this.props.height
            if (!rowSpan) {
                rowSpan = "null"    // size is auto
            }
            return `grid-row-end: span ${rowSpan};`
        },

I should not have to do that though, should I?

OK, I have worked out why it is ok on @BartButenaers' node. The problem only exists if the widget is built with NODE_ENV=development. If that is not present then the style="grid-row-end: span 4; is present as it should be.

I have submitted an issue.

3 Likes

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