External SVG use in Storybook (Angular)

Today I came across the issue to implement externally stored SVG icons in my Angular Storybook — here’s my solution.

Babette Landmesser
Feb 6 · 2 min read

When working with Design Systems or Component Libraries it’s not uncommon to use SVG icons that are stored externally.

To use external SVG icons, the HTML code usually is:

<svg aria-hidden=”true”>
<use xlink:href=”external-icons.svg#myIconID”></use>
</svg>

When opening your HTML in the browser, the console might throw an error similar to this one:

Unsafe attempt to load URL external-icons.svg from frame with URL http://localhost:9001. Domains, protocols and ports must match.

Storybook

For Storybook there’s a different project setup: Stories are rendered inside an iframe which means that the external SVG url must be callable from the inside.

Stories for an Angular project usually consists of code like this:

storiesOf('Key Visual Component', module)
.add(
'With Headline',
() => ({
component: KeyVisualComponent,
props: {
image: text('Images', 'myImage.png'),
headline: text('Headline', 'This is a headline'),
}
});

In the HTML there are now external SVGs used like the code snippet before. So, how to get rid of this error message?

svg4everybody

It’s a common workaround to use a kind of a polyfill to make the SVGs available. The most popular one might be svg4everybody.

For this case here, the component should not implement the JavaScript to keep it clean. The surrounding app should implement polyfills like this.

Where to put the polyfill now for Storybook?

Within the storybook configuration there’s an option to create an html file called preview-body.html. All content from this file will be rendered into the iframe of your story.
So the svg4everybody JavaScript needs to be loaded (whether it’s from a CDN or local file it doesn’t matter).

<script src="https://unpkg.com/svg4everybody@2.1.9/dist/svg4everybody.min.js"></script>

In the next line, the function should be called:

<script>
svg4everybody();
</script>

Restart Storybook and see the result. Well.. it’s not working!

Solution

This is because the plain function call does not enable the polyfill for external sources. Extend the code with the polyfill option and restart Storybook. Now, the SVGs should be loaded correctly.

<script>
svg4everybody({ polyfill: true });
</script>

And you’re done!

By the way: The implementation in preview-body.html is not restricted to the Angular version of Storybook.

Babette Landmesser

Written by

Frontend / Angular Developer from Mainz, Germany. https://babettelandmesser.de

More From Medium

More from Babette Landmesser

Related reads

Related reads

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade