jervis-icons
v1.2.4
Published
Universal icon/image web component that works with any framework
Maintainers
Readme
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-iconsFeatures
- 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-1collapse toadd-circleby default - Flexible sizing: tokens (
xs-xl), numbers (4,24,64) as px, CSS lengths (0.5rem,1em,24px), orfree - 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 abovefree-> no inline width/height (icon fills container)numberor numeric string (for example4,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:
- Preloaded icon maps from
configureSvgIcon({ icons })(including Vite plugin inlined icons) - If
preferExternal: true: your configured external path first - Bundled inline icons
- Library fallback (
/__jervis-icons__/...) for known library icons - 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 hoverclick— toggles on clickvisible— 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(); // RestartRTL 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:bundleSVG 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
- Add SVG files to
images/svg/ - Run
npm run optimize:svgto clean them - Run
npm run buildto 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
