This is a very simple approach to making re-usable icon Blade components. First, all icons use SVG. This provides the greatest flexibility and allows any level of scaling without loss of sharpness. The great thing about any SVG icon is that it is not a fixed image, but a markup of how to render the image. Because it is a markup, it can be manipulated in code, and, therefore, becomes a great candidate for use as a Blade component. I use this approach for all icons on my site.
The Blade Components
As an example, here is the Blade component for my "circle-plus" icon, which I use to show exandandable content in tree-views and collapsed containers:
<svg version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}>
<g transform="translate(0 -280.07)" fill="none" stroke="currentColor" stroke-width="8">
<circle cx="32" cy="312.07" r="27.367"/>
<path d="m32.059 296.48-0.11722 31.179"/>
<path d="m47.59 312.02-31.18 0.0994"/>
</g>
</svg>
It's a simple SVG icon with a circle and two lines to form the plus sign in the centre.
The key points about the Blade component are:
- It includes a
viewBox
property. This is important to allow scaling. - The
<g>
element includesstroke="currentColor"
. This allows the icon to simply use the current text color. - The use of a Blade "attribute bag" via
{{ $attributes }}
. This allows additional attributes to be added to the SVG. I most often use this simply to set the dimensions. Even that can be down in multiple ways (e.g.width="24"
orclass="w-6"
).
Using an icon component
I store all of my icon Blade components in an "icons" subfolder under "components". To use an icon, I simply use <x-icons.{component name} [attributes] />
. For example:
<x-icons.circle-plus width="16" />
It is even possible to add events to the icon. For example, in my simple photo gallery Blade component, I have right and left pointing triangles to move forwards and backwards through a set of photos. With these I add the onclick
event handler directly to the SVG via the attributes bag.
<x-icons.left-triangle class="h-8" x-on:click="previousPhoto()"/>
The left-triangle icon is simply:
<svg version="1.0" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg" fill="currentColor" stroke="currentColor" {{ $attributes }}>
<path d="m42.166 55.31-24.332-25.31 24.332-25.31v50.62z" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.125"/>
</svg>
Sources for icons
I often search for icons online, sometimes just to get some inspiration. I generally use freesvg.org.
I am not very artistic but I will sometimes create simple SVG myself using Inkscape. Inkscape has a great feature that allows saving as "Optimized SVG". This reduces the SVG to the minumim amount of code required for use. If I source an icon from freesvg.org, I will always open it in Inkscape and save as an optimized SVG.
I then create a Blade component, copy in the SVG code and edit it to add {{ $attributes }}
and ensure currentColor
is used, where appropriate (sometimes it's the stroke
attribute, sometimes fill
, and sometimes both).
For some icons, I wrote the SVG directly because it was easier than creating it any other way. For example, I have an icon that I display in observation tiles when there is no image on the observation (some observations are based on sound recordings only).
<svg viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}>
<circle cx="100" cy="100" r="97" fill="none" stroke-width="4"/>
<text text text-anchor="middle" textLength="90%" lengthAdjust="spacingAndGlyphs" x="100" y="100" transform="rotate(-45 100,100)">
No Image Available
</text>
</svg>