DEV Community

immarcelo
immarcelo

Posted on

How to change VTEX IO icons

Let's focus on #hpa-cart, or the cart icon.

Image description

Step 1 - Documentation instructions

First, go to the documentation page and follow the steps to add your own iconpack.svg file.

About iconpack.svg

VTEX IO icon system is based on SVG Sprites. If you're not familiar, it's basically a big file where each SVG file is wrapped inside a Symbol (<symbol) or Group (<g>) element identified by an id. With this ID you can instantiate your SVG element throughout the codebase with the <use /> element. One of the perks here is dealing with one single file download, that can even be optimized to an inline element at top level of your document. This CSS Tricks article is a good start point.
In VTEX IO context iconpack.svg is the base file for the SVG Sprite system and contains all icons you'll see throughout native components.

Step 2 - Editing your icon

Now that you have your own version of iconpack.svg you can start your updates.
SVG Sprites use IDs and identifier, so you first need the ID of the icon you want to modify. In order to grab this ID, inspect the element and look for the <use> element href.

Image description

For the cart icon, it would be hpa-cart. Open your iconpack.svg file and search for this ID. You'll replace the content of this group by the content of the SVG file of your icon.

Image description

Now starts the tricky part.

Step 3 - Prepare your SVG

In a nutshell, SVGs for VTEX IO icons need to follow at least these 3 requirements:

  • viewBox of 16x16
  • No strokes, only fill
  • No text, unless outlined.

I'll give an example using an icon from Heroicons.

Heroicons offers a quick way to copy the SVG by hovering the icon on their landing page. Here's how it looks like:

<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
  <path stroke-linecap="round" stroke-linejoin="round" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" />
</svg>
Enter fullscreen mode Exit fullscreen mode

We have a few problems:

  • The viewBox is 24x24 (0 0 24 24)
  • <path> uses stroke

Let's fix this on Figma. Steps will be very similar for any other modern UI software, like XD.

Fixing viewBox and SVGs styles for VTEXIO

Create a new file on your UI app or open your layout file, if you're already working with one.
In my example, I don't have a working layout file, so I'll create a new one and paste the SVG icon just to show how to set your icon.

For our working case, I'll start by converting stroke to fill using Outline stroke.
Image description

Now, to fix viewBox, simply change the size of the element. Ideally, your icon should have a 1x1 aspect ration, but it might still work with a slightly different aspect ratio. In our case, I'll change the larger dimension (18, height) to 16, toggling proportional resizing.
Notice that just changing the viewBox attribute on the code will not work, since all the SVG coordinates will need to be recalculated.

Image description

That's it for editing. Now, copy your icon as SVG (most apps will have this option, if not just export it)

Adding the new icon to iconpack

Paste the copied SVG into your code editor. It will look like this:
Image description

Copy the inner content of the <svg> (but not the svg tag itself) and go back to iconpack.svg. Replace the inner content of <g> with the brand new code:

Image description

Save it and your UI should be updated with your new icon.

Image description

Changing the icon color

Notice above that our new icon has an attribute fill="black". That's not good and will cause troubles for theming. VTEX IO apply color on icons based on the parent element color, so in order to work as expected we need to change fill to currentColor. If your element do not have fill attribute, add it.

Image description

Now your icon will respond as expected to color attribute on the parent.

Image description

That's it.

FAQ

My iconpack is not updating

Since iconpack.svg is an asset, it needs a hard-refresh to work, unlike other components that respond to hot reload. It might be the case to unlink and link again.

Can I add new icons?

Sure, you can create new icons. If you want to have custom icons for a Menu item, just add them to iconpack with an ID that you'll use to reference it. I'd suggest to prefix your icon id with custom- or something that identify your theme. One benefit in using the icon for menu items is that menu-item block has it's own viewBox property, so it won't default to 16x16 like the rest of the icon system.

What if the viewBox is not 16x16?

As the example above show, it will still work if the viewBox is slightly different, since the largest dimension is not bigger than 16. But there's a caveat when it comes to not 1x1 aspect ratios. Notice on the screenshot result above our icon is aligned to the left. This happened because our icon is not a perfect 1x1. If that's not tolerable and you can't have your icon drawn within a 1x1 proportion, you'll have to fix it. One possible workaround is:

Create a 16x16 rectangle; place your icon on center of this rectangle; group them; copy the SVG code of the group.
Image description

The code will look like this. Copy all but the <rect /> element, which is the rectangle you just created.

Image description

Update your iconpack with it and now your icon should have more even side space.

Image description

Technically, this could be solved with a more robust approach like SVG preserveAspectRatio, but it's not possible to pass down custom attributes to SVG elements in VTEXIO.


SVG can be sometimes confusing and there's plenty scenarios that will require special attention. Hope this can help you at least to get started and never use ::before again!

Top comments (0)