npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

preact-svg-icon

v0.1.4

Published

Create a preact icon component from an SVG fragment URL

Downloads

7

Readme

preact-svg-icon

A Light-weight Preact SVG icon wrapper

npm add preact-svg-icon

Usage

PersonIcon.jsx

import toSvgIcon from 'preact-svg-icon';
// provide a SVG file and fragment id to use as icon
export default toSvgIcon('/person.svg', 'fragment-id');

Using the icon:

import PersonIcon from './PersonIcon';

function MyPage() {
  return <PersonIcon
    className="css-class-1 css-class-2"
    color="red"
    size={16}
    style={{ textAlign: 'center' }}
    title="Profile settings"
    titleId="profile-icon-title"
  >;
}

Run demo

npm ci
npm start
# Watch changes on a new terminal
npm run example:watch

Problem statement

Many SVG icon solutions converts SVGs to JSX when creating their icon components.

  1. This means the entire SVG is now inside your javascript file. This increases the parse and execute time. If the SVG were to be already in the HTML or downloaded by browser (like an image) then that would be more ideal.

  2. The icons are potentially repeated across JS bundles (e.g. if code splitting is used). It would be nicer if browser could cache the SVGs across pages like how regular images can be cached.

Solution

There are couple of solutions to this. One such solution that allows browsers to cache the icons is by having the icon as an .svg file, with an id on the <svg> element or on the individual elements inside of the svg tag (also known as "SVG sprite") and then at the place where you want to use the icon, use a svg <use> tag pointing to the SVG file via a "fragment URL" (fancy way of saying <url>#<id>). e.g:

<svg>
  <use href="/path/to/icon.svg#id">
</svg>

This helps us in the following ways:

  1. Less JS: Very less SVG remains in the JS bundle. Also when page code splitting is used, only the base component used to generate the <use> tag is bundled across pages; which is extremely small.
  2. Styleable: Mostly styleable (waves hand in the air). It respects css fill color. By default if you set fill="currentColor" on the SVG, then it will inherit the text color from parent. It can't do advanced styling, animations etc like an inline SVG. But for most icons, this is an acceptable trade-off. There are advanced progressive enhanced ways of converting the tag into inline SVG via JS, but I will not dvelve into thtat here.
  3. Cacheable: The SVG files could be cached by browser now across pages (using Cache-Control HTTP headers, just like images, css or js files).
  4. Preloadable: To avoid a "flash of blank space" on SVGs on the immediately visible area of a page on a page load, you could selectively preload some SVGs via link tag rel="preload" or by having some of the SVGs sprited in the HTML itself (when referencing them you can skip the URL part and keep only the fragment part - <use href="#id">). SVG sprite example:
    <svg width="0" height="0" style="display: none">
      <symbol id="icon1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
        <path d="M502.3 ..."></path>
      </symbol>
      <symbol id="icon2" ...>
        ...
      </symbol>
    </svg>
    
    <!-- Usage: How to use an SVG already in HTML -->
    <svg>
       <use href="#icon1">
    </svg>

If you have many icons to add fragment ids to, then this repo provides a node.js script inside utils/ directory to add an id to a directory full of svg files. Note: It will also remove fill attribute from <svg> element

node utils/add-svg-id.js myicon.svg
# or full directory
# node utils/add-svg-id.js .

References

  1. https://css-tricks.com/svg-sprites-use-better-icon-fonts/
  2. https://css-tricks.com/accessible-svgs/