jervis-icons

Universal icon/image web component that works with any framework
30,773
Install
npm install jervis-icons
Latest Version:1.2.4
Vue:3
License:MIT
Last Updated:Jun 25, 2026
Links: npm
Maintainer: keroloszakaria

Jervis Icons

A universal icon/image web component that works with any framework - React, Vue, Angular, Svelte, or vanilla JavaScript.

Installation

npm install jervis-icons
# or
yarn add jervis-icons
# or
pnpm add jervis-icons

Features

  • Works with any framework (React, Vue, Angular, Svelte, vanilla JS)
  • 5,900+ SVG icons — ~100 essential icons bundled inline, all available on demand
  • 28 CSS animations - spin, bounce, heartbeat, tada, and more (Lottie-like)
  • 4 animation triggers - auto, hover, click, viewport visibility
  • SVG icons with color customization
  • Image support (PNG, JPG, JPEG, WebP, GIF)
  • Smart icon resolution - bundled/local icons first by default to avoid per-icon network requests
  • Duplicate-safe names - numeric variants like add-circle-1 collapse to add-circle by default
  • Flexible sizing: tokens (xs-xl), numbers (4, 24, 64) as px, CSS lengths (0.5rem, 1em, 24px), or free
  • RTL support with automatic transformation
  • TypeScript support
  • Zero runtime dependencies

Quick Start

Vanilla JavaScript / HTML

<!-- Import the component -->
<script type="module">
  import "jervis-icons";
</script>

<!-- Use bundled icons directly by name -->
<svg-icon name="bell" size="md" color="#3b82f6"></svg-icon>
<svg-icon name="edit" size="lg" color="#10b981"></svg-icon>
<svg-icon name="trash" size="sm" color="#ef4444"></svg-icon>

<!-- Or use custom icons from your project -->
<svg-icon src="/my-icons/custom.svg" size="lg"></svg-icon>

React

import { useEffect } from "react";
import { configureSvgIcon } from "jervis-icons";

// Configure once in your app entry
configureSvgIcon({
  basePath: "/assets/images",
  locale: "en",
});

function App() {
  return (
    <div>
      <svg-icon name="home" size="md" color="#3b82f6"></svg-icon>
      <svg-icon src="/icons/star.svg" size="lg"></svg-icon>
    </div>
  );
}

// TypeScript: Add type declaration
declare global {
  namespace JSX {
    interface IntrinsicElements {
      "svg-icon": React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement> & {
          name?: string;
          src?: string;
          ext?: string;
          type?: "auto" | "svg" | "image";
          size?: string | number;
          color?: string;
          filled?: boolean;
          "read-only"?: boolean;
          transform?: boolean;
          "max-width"?: string | number;
        },
        HTMLElement
      >;
    }
  }
}

Vue 3

<script setup>
import { configureSvgIcon } from "jervis-icons";

// Configure once
configureSvgIcon({
  basePath: "/assets/images",
  locale: "ar", // For RTL support
});
</script>

<template>
  <svg-icon name="home" size="md" color="#3b82f6" />
  <svg-icon :src="iconSrc" size="lg" />
</template>

Add to vite.config.ts to avoid Vue warnings:

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag === "svg-icon",
        },
      },
    }),
  ],
});

Angular

// app.module.ts
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
import "jervis-icons";

@NgModule({
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  // ...
})
export class AppModule {}
// main.ts or app.component.ts
import { configureSvgIcon } from "jervis-icons";

configureSvgIcon({
  basePath: "/assets/images",
});
<!-- component.html -->
<svg-icon name="home" size="md" color="#3b82f6"></svg-icon>

Svelte

<script>
  import { onMount } from 'svelte'
  import { configureSvgIcon } from 'jervis-icons'

  onMount(() => {
    configureSvgIcon({
      basePath: '/assets/images'
    })
  })
</script>

<svg-icon name="home" size="md" color="#3b82f6"></svg-icon>

API

Attributes

Attribute Type Default Description
name string - Icon name (filename without extension)
src string - Direct URL to the icon/image
ext string 'svg' File extension when using name
type 'auto' | 'svg' | 'image' 'auto' Force icon type
size string | number 'md' Icon size (xs-xl, free, numbers as px, or CSS lengths like 0.5rem)
color string 'currentColor' Primary SVG color
color2 string - Secondary color for dual-tone icons
color3 string - Third color for multi-tone icons
color4 string - Fourth color for multi-tone icons
color5 string - Fifth color for multi-tone icons
filled boolean true Whether SVG is filled or stroked
read-only boolean false Shows not-allowed cursor
transform boolean true Enable RTL transformation
max-width string | number '100%' Maximum width

Size Map

Size Pixels
xs 20px
sm 24px
md 32px
lg 40px
xl 48px

Size value rules:

  • xs, sm, md, lg, xl -> mapped pixel sizes from the table above
  • free -> no inline width/height (icon fills container)
  • number or numeric string (for example 4, 24, "64") -> treated as pixels
  • CSS length string (for example "0.5rem", "1em", "24px", "50%") -> used as-is

Configuration

Use configureSvgIcon() to set global defaults:

import { configureSvgIcon } from "jervis-icons";

configureSvgIcon({
  basePath: "/assets/images", // Base path for your project's icons
  svgPath: "/assets/svg", // Specific path for SVGs
  imagePath: "/assets/images", // Specific path for images
  locale: "ar", // 'ar' enables RTL transformation
  preferExternal: false, // Bundled/local-first (default)
  iconCategory: "base", // Default: collapse numeric variants (e.g. add-circle-1 -> add-circle)
});

Icon Priority System

When you use an icon by name, svg-icon follows this priority:

  1. Preloaded icon maps from configureSvgIcon({ icons }) (including Vite plugin inlined icons)
  2. If preferExternal: true: your configured external path first
  3. Bundled inline icons
  4. Library fallback (/__jervis-icons__/...) for known library icons
  5. If preferExternal: false (default): external path fallback for unknown names

Use this when you want your project assets to override bundled names:

// Your project's "bell.svg" will be used instead of bundled one
configureSvgIcon({
  basePath: "/my-icons",
  preferExternal: true,
});
<svg-icon name="bell"></svg-icon>
<!-- Loads from /my-icons/bell.svg if exists, otherwise uses bundled -->

Bundled Icons

Jervis Icons includes ~100 essential bundled icons (available without network requests) and 5,900+ total icons. All icons use currentColor for easy styling.

import { getBundledIconNames, hasBundledIcon } from "jervis-icons";

// Get all available icon names
const icons = getBundledIconNames();
console.log(icons); // ['activity', 'add-user', 'bell', ...]

// Check if an icon is bundled
if (hasBundledIcon("bell")) {
  console.log("bell icon is available!");
}

Get deduplicated names and categories:

import { getAllIconNames, getIconCategories } from "jervis-icons";

const names = await getAllIconNames(); // default config -> deduplicated base names
const categories = await getIconCategories();

Vite: Avoid Per-Icon HTTP Requests

Use the Vite plugin to auto-inline only referenced library icons:

// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { jervisIcons } from "jervis-icons/vite";

export default defineConfig({
  plugins: [vue(), jervisIcons()],
});

With this plugin, commonly used library icons are served from an in-memory map (no per-icon request), while unknown icons still fall back safely.

Available icons include:

  • UI icons: edit, trash, close, check, plus, search, filter, menu...
  • Navigation: arrow-left, arrow-right, chevron-down, chevron-right...
  • File types: pdf, doc, xls, zip, jpg, png, mp4...
  • Actions: download, upload-cloud, export, reload, logout...
  • Status: success, error, warning, info_circle...
  • And many more!

Custom Tag Name

Register with a custom tag name:

import { register } from "jervis-icons";

register("my-icon"); // Use as <my-icon>

Examples

Basic SVG Icon

<svg-icon name="home" size="md" color="#3b82f6"></svg-icon>

Direct URL

<svg-icon src="https://example.com/icon.svg" size="lg"></svg-icon>

Custom Size (Pixels)

<svg-icon name="star" size="64"></svg-icon>
<svg-icon name="star" size="4"></svg-icon>

Custom Size (CSS Length)

<svg-icon name="star" size="0.5rem"></svg-icon>
<svg-icon name="star" size="1em"></svg-icon>
<svg-icon name="star" size="24px"></svg-icon>

Image (PNG)

<svg-icon name="logo" ext="png" size="xl"></svg-icon>

Outlined Style

<svg-icon name="heart" filled="false" color="red"></svg-icon>

Disabled State

<svg-icon name="edit" read-only></svg-icon>

Animations

Add smooth Lottie-like animations to any icon with zero extra dependencies:

<!-- Spinning loader -->
<svg-icon name="settings" animate="spin"></svg-icon>

<!-- Bounce on hover -->
<svg-icon name="bell" animate="bounce" animate-trigger="hover"></svg-icon>

<!-- Heartbeat on click toggle -->
<svg-icon
  name="heart"
  animate="heartbeat"
  animate-trigger="click"
  color="#ef4444"
></svg-icon>

<!-- Custom speed & timing -->
<svg-icon
  name="star"
  animate="pulse"
  animate-duration="0.5s"
  animate-timing="linear"
></svg-icon>

Available Animations

Category Animations
Looping spin, spin-reverse, pulse, bounce, float, heartbeat, fade, ping, swing
Attention shake, wiggle, tada, jello, rubber-band, flash, wobble
3D flip, flip-x, flip-y
Entrances fade-in, zoom-in, roll-in, slide-in-left, slide-in-right, slide-in-up, slide-in-down
Exits fade-out, zoom-out

Animation Triggers

  • auto — starts immediately (default)
  • hover — plays on mouse hover
  • click — toggles on click
  • visible — plays when element enters viewport

Programmatic Control

const icon = document.querySelector("svg-icon");
icon.startAnimation(); // Start
icon.stopAnimation(); // Stop
icon.pauseAnimation(); // Pause
icon.resumeAnimation(); // Resume
icon.replayAnimation(); // Restart

RTL Support

configureSvgIcon({ locale: "ar" });
<!-- Will be mirrored automatically -->
<svg-icon name="arrow-right"></svg-icon>

<!-- Disable transformation for specific icons -->
<svg-icon name="logo" transform="false"></svg-icon>

Building from Source

# Install dependencies
npm install

# Development
npm run dev

# Build (includes SVG optimization and bundling)
npm run build

# Optimize SVGs only
npm run optimize:svg

# Generate SVG bundle only
npm run generate:bundle

SVG Guidelines

All bundled SVGs follow these guidelines:

  • No hardcoded colors - uses currentColor
  • No width/height attributes - scales via CSS
  • Optimized and minified
  • viewBox preserved for proper scaling

Adding Custom Icons to the Package

  1. Add SVG files to images/svg/
  2. Run npm run optimize:svg to clean them
  3. Run npm run build to regenerate the bundle

Browser Support

Works in all modern browsers that support Web Components (Custom Elements v1):

  • Chrome 67+
  • Firefox 63+
  • Safari 10.1+
  • Edge 79+

License

MIT

Related Packages

js-rich-body-highlighter

Premium, framework-agnostic muscle map. Highlights muscles with mix-blend-mode o...

3,030 3
@studiolxd/scorm

Headless SCORM 1.2/2004 runtime — framework-agnostic core with React, Vue, Angul...

1,855 0
sagegreytechnologies-nkiru-ai-chat-widget-webcomponent

Native Web Component chat widget with complete CSS isolation using Shadow DOM

1,532
@yzfe/svgicon-loader

Webpack loader to load svg icon

64,575 911
@aspect-ui-01/toast

Lightweight framework-agnostic toast notifications (~2KB)

3,926

Version History

Version Released License
1.2.4 MIT
1.2.2 MIT
1.2.1 MIT
1.2.0 MIT
1.1.0 MIT
Pre-releases (11)
Version Released License
1.0.3-alpha.9 MIT
1.0.3-alpha.8 MIT
1.0.3-alpha.7 MIT
1.0.3-alpha.6 MIT
1.0.3-alpha.5 MIT