Tomer
Tomer

Reputation: 17940

using svg sprite with vue storybook

I've created an app using the latest Vue CLI.

I'm using vue-storybook to generate a styleguide.

I have an SVG Sprite file under assets called icons.svg and i'd like to create an Icon.vue component that accepts the name of the icon and displays it from the sprite.

The component looks like this:

//currently the href is hardcoded for testing purposes, 
//later on it would be passed as a property
<template>
    <svg class="icon">
        <use xlink:href="../assets/icons.svg#icon-compliance"></use>
    </svg>
</template>

<script>
export default {
  name: "AqIcon"
};
</script>

<style scoped>
.icon {
  display: inline-block;
  width: 1rem;
  height: 1rem;
  fill: red;
}
</style>

And i have a simple story to display it:

storiesOf("Icon", module).add("Icon", () => ({
  components: { AqIcon },
  template: "<AqIcon />"
}));

The problem is the browser tries to load http://localhost:6006/assets/icons.svg and can't find it, I tried all kind of urls but i can't seem to figure out the correct one.

Also, how can i make it dynamic?

Upvotes: 4

Views: 3460

Answers (2)

Jesse Fried
Jesse Fried

Reputation: 21

Include an SVG sprite in your markup by making it it's own Vue component. In my case I put the SVG sprite component in App.vue.

App.vue:

<template>
  <div class="body">
      <YourOtherComponents />
      <SvgSprite />
  </div>
</template>

<script>
import YourOtherComponents from './Components/YourOtherComponents.vue';
import SvgSprite from './Components/SvgSprite.vue';

export default {
  name: 'App',
  components: {
    YourOtherComponents,
    SvgSprite,
  },
};
</script>

SvgSprite.vue:

<template>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: none;">
    <symbol id="arrow-left" viewBox="0 0 24 24">
      <polyline points="15 18 9 12 15 6"></polyline>
    </symbol>
    <symbol id="arrow-right" viewBox="0 0 24 24">
      <polyline points="9 18 15 12 9 6"></polyline>
    </symbol>
  </svg>
</template>

<script>
export default {
  name: 'SvgSprite',
};
</script>

This way you can the svgs just as if the sprite was inline in your project's index.html file. It's just cleaner.

Upvotes: 0

acdcjunior
acdcjunior

Reputation: 135812

You can use require(). Just make sure you don't parameterize its whole args (I mean, leave the folder and extension as hardcoded strings).

In the example below, WebPack will load all .svg files of the /assets folder (because they may be requested during runtime).

<template>
    <svg class="icon">
        <use :xlink:href="src"></use>
    </svg>
</template>

<script>
export default {
  name: "AqIcon",
  props: ['icon'],
  computed: {
    src() {
      return require('../assets/' + this.icon + '.svg')
    }
  }
};
</script>

Upvotes: 6

Related Questions