[SalesForce] Summer 18: SVG blocked in Lightning Components

The old approach of using a helper component to display SVG in Lightning now appears to be blocked in Summer 18. What is a bit alarming, though, is that even components marked with API version 40-42 are also seeing it fail in Summer 18.

An example of such a helper component is Strike SVG from Appiphony:

https://github.com/appiphony/Strike-Components/tree/master/aura/strike_svg

In which a custom Renderer creates the SVG element, creates the USE element, and attaches the href to it. In Summer 18 it creates the elements correctly but fails to attach the href to the USE element.

The root cause of this behaviour change would appear to be this commit to LockerService:
https://github.com/forcedotcom/aura/commit/495eaccdc3292a6cf2dcd2c2347c0329c06339e0

Now it also happens to be the case that we're being encouraged to use lightning:icon instead. And I do see that in Summer 18 there is a new src attribute even available for custom SVG paths. That's all pretty cool. But there are certain SLDS blueprints I cannot reproduce using lightning:icon.

One example is the advanced Data Table. Due to some places where lightning:dataTable is still not flexible enough for our needs, I have written a component that constructs the table manually and was trying to add the nifty sort UI where you hover over the column header and see an arrow appear to indicate that clicking there will sort it. See here: https://www.lightningdesignsystem.com/components/data-tables/ (click Advanced under Variants).

The following snippet is included in that blueprint markup to render said arrow:

      <div class="slds-icon_container">
        <svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true">
          <use xlink:href="/assets/icons/utility-sprite/svg/symbols.svg#arrowdown" xmlns:xlink="http://www.w3.org/1999/xlink" />
        </svg>
      </div>

Note that it's asking us to put the class slds-is-sortable__icon on the SVG tag itself. Suppose I attempt to implement this using lightning:icon. So I try the following:

<lightning:icon iconName="utility:arrowdown" class="slds-is-sortable__icon"
                    size="x-small" />

When I render that in a Lightning component and Inspect Element this is what I get:

<lightning-icon class="slds-is-sortable__icon slds-icon-utility-arrowdown slds-icon_container" data-aura-rendered-by="87:0">
    <lightning-primitive-icon lightning-primitive-icon_primitive-icon="">
        <svg focusable="false" data-key="arrowdown" aria-hidden="true" class="slds-icon slds-icon-text-default slds-icon_x-small" lightning-primitive-icon_primitive-icon="">
            <use xlink:href="/_slds/icons/utility-sprite/svg/symbols.svg?cache=9.8.0#arrowdown" lightning-primitive-icon_primitive-icon=""/>
        </svg>
    </lightning-primitive-icon>
</lightning-icon>

Note that the slds-is-sortable__icon class was applied to the wrapper instead of the SVG itself. And indeed, the outcome is not the desired one: Because the sortable class is placed on an outer element instead of the correct one, the styles cascade incorrectly. Since lightning:icon does not have any way to add custom classes directly to the SVG tag, the blueprint is impossible to reproduce in a Summer 18 Lightning Component. In Spring 18 my workaround was to import Strike SVG and use that to place the class on the SVG tag, but now that's unusable.

Any thoughts?

Best Answer

You'll want to ask about this over on the Collaboration groups at success.salesforce.com, as well as perhaps logging a bug with Technical Support. I'm not sure how far we'll get with it, but it doesn't hurt to get started on it before the public release.

In the meantime, you can still work around the problem, it's just non-trivial. Using my progressRing example, the source you've linked implies we can still use path, rect, and other SVG elements, so you could copy-paste the actual paths from the resources and convert them to code similar to my design.

Obviously, this will limit your ability to keep up to date with the current SLDS, although I suspect another alternative would be to download the public assets (e.g. "apexpages/slds/latest/assets/icons/utility-sprite/svg/symbols.svg"), parse it manually using a DocumentFragment, find the appropriate path, and then attach it as a child of the SVG tag. I'm going to experiment with this, but please feel free to let me know if you get it working.

Finally, as an absolute fallback, consider using the PNG-based images instead, which you may need to download as a static resource. I hate recommending this, because it's terribly inflexible, but it would at least be a temporary stopgap until you can come up with a more permanent solution.

Related Topic