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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hoyasumii/skill-icons

v0.1.0

Published

370+ tech, language and tool icons with dark and light themes, as lazy-loaded SVG components for React, Vue, Svelte, Angular, Solid, Astro and Web Components.

Downloads

106

Readme

@hoyasumii/skill-icons

Skill icons as components. One package, one entry point per framework.

npm install @hoyasumii/skill-icons   # or: pnpm add / yarn add / bun add

React

import { Icon, Icons } from '@hoyasumii/skill-icons/react';

<Icon name="react" />
<Icon name="ts" theme="light" size={32} />
<Icons names={['js', 'ts', 'react']} perLine={2} />

Solid

import { Icon, Icons, SkillIconsProvider } from '@hoyasumii/skill-icons/solid';

<Icon name="solidjs" />
<Icons names={['js', 'ts', 'solidjs']} perLine={2} />

Requires solid-js 1.8 or newer. The package ships the solid export condition (preserved JSX, compiled by your Solid plugin) plus compiled DOM and SSR builds as fallback. Props are read reactively, so signals work as usual.

Vue

<script setup lang="ts">
import { Icon, Icons } from '@hoyasumii/skill-icons/vue';
</script>

<template>
  <Icon name="react" />
  <Icon name="ts" theme="light" :size="32" />
  <Icons :names="['js', 'ts', 'react']" :per-line="2" />
</template>

Names are checked in templates by vue-tsc and Volar.

Svelte

Svelte 5 or later. Components ship as .svelte source, so your Svelte toolchain compiles them.

<script lang="ts">
  import { Icon, Icons } from '@hoyasumii/skill-icons/svelte';
</script>

<Icon name="react" />
<Icon name="ts" theme="light" size={32} />
<Icons names={['js', 'ts', 'react']} perLine={2} />

Names are checked in templates by svelte-check.

Angular

Standalone components with signal inputs. Requires @angular/core 17.1 or newer (the first version with input()).

import { Component } from '@angular/core';
import { Icon, Icons } from '@hoyasumii/skill-icons/angular';

@Component({
  imports: [Icon, Icons],
  template: `
    <skill-icon name="react" />
    <skill-icon name="ts" theme="light" [size]="32" />
    <skill-icons [names]="['js', 'ts', 'react']" [perLine]="2" />
  `,
})
export class Skills {}

SKILL_ICONS bundles Icon, Icons and SkillIconsProvider for a single imports entry.

Angular inputs can't express "typed names in local mode, any string with latest", so name and names accept IconName | (string & {}): known names still autocomplete, but a typo is not a compile error. In local mode an unknown name renders nothing.

Class and style set on the element itself (<skill-icon class="x">) apply to the host element, not the <img>. To style the image use imgClass and imgStyle (any value Angular's [class] and [style] bindings accept), and alt to override the alt text:

<skill-icon name="react" imgClass="rounded" [imgStyle]="{ opacity: 0.8 }" alt="React" />

Astro

Astro 4 or later. Components ship as .astro source and render fully on the server: the SVGs are inlined as data URIs, with no client JavaScript and no loading state.

---
import { Icon, Icons } from '@hoyasumii/skill-icons/astro';
---

<Icon name="react" />
<Icon name="ts" theme="light" size={32} />
<Icons names={['js', 'ts', 'react']} perLine={2} />

Props match React's, and extra attributes (class, style, alt, ...) are passed to the <img>. Names are checked in .astro files by astro check. theme="auto" renders a <picture> that follows the visitor's color scheme.

Astro has no context, so there is no provider. Pass theme to each component, or wrap them in your own component with a default:

---
// components/TechIcon.astro
import { Icon } from '@hoyasumii/skill-icons/astro';
import type { ComponentProps } from 'astro/types';

const { theme = 'auto', ...props } = Astro.props as ComponentProps<typeof Icon>;
---

<Icon {...props} theme={theme} />

Web Component

Framework-free custom elements, with no dependencies. Register them once, then use the tags anywhere (plain HTML, Astro, Lit, ...):

<script type="module">
  import '@hoyasumii/skill-icons/element/define'; // or: import { defineSkillIcons } from '@hoyasumii/skill-icons/element'
</script>

<skill-icon name="react" theme="light" size="32"></skill-icon>
<skill-icons names="js,ts,react" per-line="2" theme="auto"></skill-icons>

Attributes are name, names (comma separated), theme, size, per-line, latest, base-url, plus alt and img-class for the generated <img>. Each one has a matching property (el.names = ['js', 'ts'], el.perLine = 2, el.latest = true) and changing either re-renders. Behavior matches the other entries: cached icons render synchronously, the previous icon stays while a new one loads, 'auto' uses a <picture>, and unknown names render nothing.

The elements render into the light DOM, so style the <img> with your own CSS or img-class. They are display: inline hosts, and the loading placeholder is a sized inline-block <span>; no global CSS is injected. defineSkillIcons() is idempotent and does nothing on the server, and importing the module never touches the DOM. Only element/define has side effects, so the rest stays tree-shakable.

Use <skill-icons-provider theme="auto"> to set the theme for everything inside. Icons find the nearest provider with a theme by walking up their ancestors (across shadow roots), so a provider without theme inherits from the outer one and an icon's own theme wins. When a provider's theme changes, it calls refresh() on the icons below it. Icons inside a different shadow root than the provider are found at connect time only.

Props

Each icon is bundled as its own chunk and only downloaded when rendered.

| Prop | Default | Description | | ------------------- | ---------------------------------------------- | ------------------------------------------------ | | name / names | | Icon names or aliases (js, ts, k8s, ...) | | theme | 'dark' | 'dark', 'light' or 'auto' | | size | 48 | Size of one icon, in pixels | | perLine (Icons) | 15 | Icons per line, from 1 to 50 | | latest | false | Load from the deployed API instead of the bundle | | baseUrl | https://skill-icons.alanreisanjo.workers.dev | API to load from, in latest mode only |

Any other prop or attribute is passed to the underlying <img> (in Angular, through imgClass, imgStyle and alt).

Themes

theme applies to icons that have dark and light variants. 'auto' follows the system's color scheme through a <picture>, so it works without JavaScript and during SSR:

<Icon name="react" theme="auto" />

To set the theme for a whole tree, use the provider. A theme prop still wins, and a provider without theme inherits from the outer one:

import { SkillIconsProvider } from '@hoyasumii/skill-icons/react'; // or /solid, /vue, /svelte, /element (as <skill-icons-provider>)

<SkillIconsProvider theme="auto">
  <App />
</SkillIconsProvider>;

In Angular, use the <skill-icons-provider theme="auto"> component, or provideSkillIcons({ theme }) in bootstrapApplication, a route or a component's providers. theme may be a signal, so a theme toggle updates every icon:

bootstrapApplication(App, {
  providers: [provideSkillIcons({ theme: 'auto' })], // or a Signal<ThemeOption>
});

When the theme changes, icons keep showing the previous variant until the new one loads, so toggling doesn't flash placeholders.

If your site has its own theme toggle, pass its current value instead of 'auto':

const { resolvedTheme } = useTheme(); // e.g. next-themes

<SkillIconsProvider theme={resolvedTheme === 'light' ? 'light' : 'dark'}>

latest mode

By default, names are typed against the icons bundled with the installed version. With latest, any string is accepted and icons load from the deployed API at runtime, so new icons work without updating the package:

<Icon latest name="some-new-icon" />
<Icons latest names={['js', 'some-new-icon']} baseUrl="https://my-deploy.dev" />

HTML string

For SSR without a framework, emails or static site generators, the core (@hoyasumii/skill-icons) renders the same markup as the components:

import { renderIcon, renderIcons } from '@hoyasumii/skill-icons';

await renderIcon('react', { theme: 'auto', size: 32, attrs: { class: 'icon', loading: 'lazy' } });
await renderIcons(['js', 'ts', 'react'], { perLine: 3 });
await renderIcon('some-new-icon', { latest: true, baseUrl: 'https://my-deploy.dev' }); // remote URL

Both return a Promise<string>: an <img> with an inlined data URI (wrapped in a <picture> for theme: 'auto'), or '' for unknown names in local mode. Attribute values are escaped and invalid attribute names are skipped.