New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support inline SVG icons #3155
Comments
This limitation is in fact a real issue for deployments on systems with limited storage resources. The MDI web font is some orders of magnitude larger than my application, and there is currently no alternative to the (discouraged) way of embedding all icons through the font. @dword-design maybe a PR is worth a shot to demonstrate how things would look like? |
I've also been concerned about this due to the size of the MDI font, to the extent that I started exploring creating my own replacement icon component... and at this point I realised it's not difficult to use inline SVG icons through the existing Buefy icon component!
<template>
<component :is="iconName"></component>
</template>
<script>
import { ArrowRightIcon, CheckIcon } from 'vue-feather-icons'
export default {
components: {
ArrowRightIcon,
CheckIcon
},
props: ['icon','size'],
computed: {
iconName: function() {
return `${ this.icon[1].replace(/-./g, x=>x.toUpperCase()[1]).replace(/\b\w/g, c => c. toUpperCase()) }Icon`;
}
},
}
</script>
<style lang="scss">
.icon svg {
stroke-width: 2 !important;
fill: none !important;
}
</style>
|
@johnpuddephatt Oh wow that's actually a great solution. At least way better than the hackery I'm using right now. I think we still need the issue so we can directly pass the icons through and have compile-time checks like unused icon imports etc. Haven't tried the alternative by @johnpuddephatt yet, I'll write in case there's anything. |
@johnpuddephatt Thank you for this, it was a great help to me. Just to expand on your solution with some extra details: To the To the There is also a third prop You can see in Buefy's Icon component where Buefy instantiates a custom icon component: <component
v-else
:is="useIconComponent" // this will dynamically load in our SvgIcon component
:icon="[newPack, newIcon]"
:size="newCustomSize"
:class="[customClass]"/> Vue feather icons take a size and class prop. We can pass these through using v-bind: <template>
<component :is="iconName" v-bind="iconProps"></component>
</template>
<script>
// ...
props: ['icon','size','class],
computed: {
iconName: function() {
// ...
},
iconProps: function() {
return { size: this.size || '1x', class: ...this.class || '' }
},
},
}
</script> Then something like the below should pass through the <b-icon icon="arrow-right" customSize="4x" customClass="my-class"> |
@johnpuddephatt @End-S Thanks for the solutions. I have been using Bootstrap-Vue for a few of my past projects and I feel that their approach of using slots to allow basically any type of icon works quite well. Perhaps this could be considered? |
@arthur-clq Isn't this exactly like it's done in Buefy with a <template>
<div class="h2 mb-0">
<b-icon-arrow-up></b-icon-arrow-up>
<b-icon-exclamation-triangle-fill></b-icon-exclamation-triangle-fill>
</div>
</template> <template>
<div class="h2 mb-0">
<b-icon icon="arrow-up"></b-icon>
<b-icon icon="exclamation-triangle"></b-icon>
</div>
</template> |
@dword-design Hi, sorry I meant for other components. For example Bootstrap-Vue button allows a default slot, so if I do not want to use the I think this approach could be considered because it gives more flexibility given that |
@arthur-clq Alright I see. Makes sense to me or make the icon data type more flexible in Buefy. |
I got into this topic again and one downside of @johnpuddephatt s solution is that you cannot use the vue/no-unused-components rule when passing the icon components to the |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
@dword-design I opened a new discussion for improving the flexibility of |
Description
Currently the icon system depends on icon fonts. Meaning you set a class and that class sets a special font family that contains the respective icons.
This approach has its pros and cons. On the pro side is the ease of use because you can just set a class and you have an icon. On the con side is the bundle size and the page loading time. Explicitly setting the icon set leads to dependencies between the components and the app config.
A different approach is to directly render inline SVGs instead. There are webpack loaders that allow to load SVG files and use them as components. Then you can do something like this:
This is currently not working with Buefy because the
b-icon
component requires the icon property to be a string, and then constructs css classes and passes them to the underlyingdefaultIconComponent
. You have to create the icons yourself without usingb-icon
(see above). Also, you cannot useb-button
and the dialog system, which implicitly useb-icon
. A better approach would be to leave the class creation to thedefaultIconComponent
and to widen up the allowed icon types to objects and strings, so we can pass the SVG icon through. Then you could do things like this:I've successfully used the approach in this project by mainly directly using the bulma classes and would love use it within Buefy.
Why Buefy need this feature
It allows to use the common technique of inline SVG icons with Buefy to decrease the bundle size and remove the dependency between the component and the app config.
Looking forward to your thoughts. I'm also open to contributing a PR if people like the idea.
The text was updated successfully, but these errors were encountered: