bartbutenaers / node-red-contrib-ui-svg

A Node-RED widget node to show interactive SVG (vector graphics) in the dashboard
Apache License 2.0
94 stars 27 forks source link

Fill problem from Illustrator #98

Closed la9vka closed 2 years ago

la9vka commented 2 years ago

Is there a reason for this to be in the code? I have not experienced any adverse effects when deleting this, but it allows me to directly use illustrator made graphics without the fill problems.

svg_graphics.js line 187

.nr-dashboard-theme .nr-dashboard-template div.ui-svg path { fill: inherit; }

bartbutenaers commented 2 years ago

Hi @la9vka, We had a lot of problems in the past with fill colors. Not sure anymore about this one. @Steve-Mcl : does this ring a bell to you?

Steve-Mcl commented 2 years ago

@bartbutenaers yes, it rings a distant bell. Something to do with dashboard styles and fill colour of shapes. Does the commit history for that line help?

Steve-Mcl commented 2 years ago

If this "opinionated" option is an issue, we could provide an advanced checkbox option of "inherit dashboard style" (set true by default)?

bartbutenaers commented 2 years ago

Hey @Steve-Mcl , Thanks for joining!!! That code has been introduced via this commit, which you have explained on Discourse at the time being.

Yes indeed I can add such a textbox. But - if your memory is better than mine - do you remember:

  1. Whether it is enough to only generate or skip the line .nr-dashboard-theme .nr-dashboard-template div.ui-svg path { fill: inherit; } ?
  2. An easy explanation that I can add to the info panel and readme page, to explain a bit simple what this option does?
la9vka commented 2 years ago

I had no problem with any other dashboard nodes removing it so a config option would be great.

"Disable SVG path fill inheritance" "Enabling this disabled the path fill inheritance. This may solve problems importing graphics from other programs."

Steve-Mcl commented 2 years ago

@bartbutenaers

I hate to say this, but to be 100% flexible, perhaps we add a style tab with it defaulted to ...

    div.ui-svg svg{
        color: var(--nr-dashboard-widgetColor);
        fill: currentColor !important;
    }
    div.ui-svg path {
        fill: inherit !important;
    }

That way, @la9vka can remove or tweak as required?

Alternatively, we simply enable/disable this "opinionated" style via a checkbox?

bartbutenaers commented 2 years ago

@Steve-Mcl Suppose I add a style tabsheet. If you have N svg nodes in a flow, how do we make sure that the the custom styles of each node are only applied to the svg shapes of that node? Because otherwise it might become confusing imho.

Steve-Mcl commented 2 years ago

Good question. I guess it would have to be scoped.

<style scoped>

And, thinking about it, even a checkbox to disable the styling would need the style to be scoped otherwise a second SVG node would still introduce the style.

bartbutenaers commented 2 years ago

Scoped styles. Never heard about it. Will need to have a look first... Thanks for the pointers!!!

bartbutenaers commented 2 years ago

Have not tested it yet, but from this stackoverflow discussion I understand that scoped svg styles have been removed from the specs? But perhaps I am misinterpreting it. Did only a quick search...

bartbutenaers commented 2 years ago

Indeed the scoped css doesn't seem to work in an SVG, as you can see in my test. Instead of a red and a blue circle, I get two blue circles ...

bartbutenaers commented 2 years ago

Following this Stackoverflow discussion, it should be possible via a shadow DOM. But seems at first sight a rather big change of the svg-node to me...

Steve-Mcl commented 2 years ago

2 easier options to explore 1st...

If we don't add any other styles (other than in #45758bf) to the class .ui-svg we could (via a checkbox option) simply remove the class='ui-svg' meaning the specific SVG node won't inherit the styling.

Alternatively, we could scope the CSS by specificity. E.g use '#svggraphics_' + config.id + ' .ui-svg.etc.etc' in the CSS specifiers.

bartbutenaers commented 2 years ago

Hmm that scoping by specificity is a nice workaround! I assume we cannot add the '#svggraphics_' + config.id + automatically. So the user will need to specify it manually all over the place. Which will make the css less readable and understandable...

bartbutenaers commented 2 years ago

I assume we cannot add the '#svggraphics_' + config.id + automatically.

Perhaps the CSS can be modified at server side already via the postcss-prefix-selector...

Steve-Mcl commented 2 years ago

I assume we cannot add the '#svggraphics_' + config.id + automatically.

I'm sure we could - by including '#svggraphics_' + config.id here and here as part of the specifier to make it more specific

e.g...

        var html = String.raw`
<style>
    .nr-dashboard-theme .nr-dashboard-template ` +  ' #svggraphics_' + config.id +  `  svg {
        color: var(--nr-dashboard-widgetColor);
        fill: currentColor;
    }
    .nr-dashboard-theme .nr-dashboard-template ` +  ' #svggraphics_' + config.id +  `  path {
        fill: inherit;
    }
</style>`
    + panzoomScripts + `
<div id='tooltip_` + config.id + `' display='none' style='z-index: 9999; position: absolute; display: none; background: cornsilk; border: 1px solid black; border-radius: 5px; padding: 2px;'></div>
<div class='ui-svg' id='svggraphics_` + config.id + `' ng-init='init(` + configAsJson + `)' style="width:100%; height:100%;">` + svgString + `</div>

`;              
        return html;
bartbutenaers commented 2 years ago

Hi Steve, Yes that is absolutely correct. We can do it indeed like that if we would implement a checkbox. But assume a new tabsheet is added, where CSS style can be entered. I was wondering if I could youse that postcss-prefix-selector to add a prefix '#svggraphics_' + config.id` to every selector that has been entered in that new tabsheet. To make sure that the entered styles are only applied to the svg shapes in this svg-node only...

Steve-Mcl commented 2 years ago

Hmmmm.

An "easy" way of achieving that would be to wrap the CSS in an outer selector and run it through an scss processor.

Example... Screenshot_20210924-105423.jpg

https://www.cssportal.com/scss-to-css/

Let me think some more on this one.

bartbutenaers commented 2 years ago

@Steve-Mcl : thanks for your help! Don't hurry, because I have no time at the moment to implement this...

bartbutenaers commented 2 years ago

run it through an scss processor.

@Steve-Mcl : would like to create a minor release, but would like to have this solved. Do you mean that I have to pass the default/entered CSS through a scss processor library on the server side, and then append it to the html string to send it to the client? I am not familiar with scss to be honest ...

Steve-Mcl commented 2 years ago

Yes. That was the suggestion. It gaves a way to maintain the original CSS while permitting the user to adjust it BUT keeping it scoped per instance.

I have no idea what this will add to the install size nor can I recommend a preprocessor (sorry)

bartbutenaers commented 2 years ago

Hi @la9vka, @Steve-Mcl,

I have created a customizable-css branch, which adds the following:

  1. An extra "CSS" tabsheet is added to the config screen.
  2. The tabsheet has buttons to expand to fullscreen mode, format/beautify the CSS, reset the CSS to the default.
  3. The original CSS is entered automatically by default.
  4. The readme page has been extended with information and an example flow.
  5. Migration code has been added to make sure existing nodes get the default original CSS.

I have spend most time to implement the fullscreen expand button for the CSS editor...

Due to limited free time, I have not been experimenting with all options. But I have used the postcss-prefix-selector library to add a prefix ("#svggraphics_" + config.id) to all the entered CSS selectors, in order to simulate scoped CSS (by applying the selectors only to the parent DIV element).

Since CSS is not really my cup of tea, I would appreaciate a lot if you guys could install that version and test it!! You can install it like this (within your .node-red folder):

npm install bartbutenaers/node-red-contrib-ui-svg#customizable-css

Some things I doubt about:

  1. Not sure whether the CSS mode of the editor has been setup entirely correctly, because I get some warning on the default CSS:

    image

  2. Not sure whether the beautify rules are sufficient (because there are more options)?

  3. Not sure whether my selector prefix is good enough, or should I use another one?

  4. Others?

Thanks!

Steve-Mcl commented 2 years ago

Not sure whether the CSS mode of the editor has been setup entirely correctly, because I get some warning on the default CSS

ACE doesnt have great support for newer features like var(--x). Looks fine in monaco...

image

Not sure whether my selector prefix is good enough, or should I use another one?

Your CSS selector is not working - it is rendering as ...

#svggraphics_4a3ef0db9601ba54 div.ui-svg svg{
    color: var(--nr-dashboard-widgetColor);
    fill: currentColor !important;
}
#svggraphics_4a3ef0db9601ba54 div.ui-svg path {
    fill: inherit !important;
}

but they wont work. Need to be div#svggraphics_4a3ef0db9601ba54.ui-svg svg and div#svggraphics_4a3ef0db9601ba54.ui-svg path

Example... image


NOTE

It is quire difficult to achieve that CSS so it might prove more efficient to wrap the whole output in a div with the class set to the ID of the current div wrapper e.g...

image

Then, what you have will work with a slight tweak...

const scopedCssString = postcss().use(prefixer({
          //prefix: "#svggraphics_" + config.id
          prefix: ".svggraphics_" + config.id // << use new wrapper div class name
        })).process(cssString).css;

image

image

Steve-Mcl commented 2 years ago

Also Bart, you are using ACE specific stuff so errors occur when monaco is used... image

You might be better to store the selected TAB in node.tabs = RED.tabs.create({ e.g.

                    node.currentTab = tab.id; //ADD THIS
bartbutenaers commented 2 years ago

Hey @Steve-Mcl,

A tremendous thank-you for this in depth code review, and the enhancement tips!!!! I have update the branch and hopefully everything is fine now.

I also implemented another fix: the older nodes have a dot in their node id. Seems that the dot results in the style not being applied to the element. So I have replaced the dot by an underscore, which seems to solve it.

Will announce a beta on Discourse, so people can test it. Just to avoid that I have broken something in existing flows...

bartbutenaers commented 2 years ago

I have merged it into the master branch.

bartbutenaers commented 2 years ago

@la9vka, It would be nice if you could install the 2.3.0 version from Github, using the following command (in your .node-red folder):

npm install bartbutenaers/node-red-contrib-ui-svg

I would like to know whether your problem is solved in this version? And this version contains a large number of changes, so it would be nice if anybody could test it ... Bart

la9vka commented 2 years ago

gencontrol-svg2 3 0-test Not yet tested the larger svg's but looks good. One with modified css and one with original in the same dashboard group. Both with svg straight from illustrator.

la9vka commented 2 years ago

I have yet to find any issues on any of my old flows (previously run on unchanged 2.2.4). Please let me know if there is anything spesific you want me to test. Otherwise close the issue. Thanks for the amazing work :)

bartbutenaers commented 2 years ago

Hi @la9vka, Thanks for the offer!!! To be honest I have no idea what could be wrong with those changes, so we will have to release it and wait for feedback... But I am still waiting for feedback about issues reported (about another new feature in this 2.3.0 release), before I can publish it on NPM ;-( Bart

bartbutenaers commented 2 years ago

Hi @la9vka,

FYI: Version 2.3.0 is now available on NPM and in the palette

image