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

@genarou/blazir-icons

v1.4.3

Published

A high-performance Svelte 5 icon library with smart caching, lazy loading, presets, variants, and a declarative effects system.

Readme

blazir-icons

A high-performance Svelte 5 icon library with smart caching, lazy loading, presets, variants, and a declarative effects system.

  • 199 icons — original SVG artwork
  • Svelte 5 runes$props, $derived, $effect
  • Three usage patterns — dynamic <Icon>, lazy <IconLazy>, or direct named imports
  • Smart LRU cache — referential stability, zero re-renders on stable props
  • Lazy loading — per-icon code splitting via import()
  • Vite plugin — automatic tree shaking, only used icons in the bundle
  • Full TypeScript — autocomplete on every prop, icon name, preset, and variant
  • Accessiblearia-label, title, decorative support out of the box

Table of Contents


Installation

npm install @genarou/blazir-icons
# or
pnpm add @genarou/blazir-icons

Peer dependency: Svelte 5


Quick Start

<script>
  import { Icon } from '@genarou/blazir-icons'
</script>

<Icon name="check" />
<Icon name="home" size={24} color="var(--primary)" />
<Icon name="settings" preset="muted" />
<Icon name="trash" variant="danger" />

The CSS animation stylesheet is injected automatically on import. No manual CSS setup required.


How It Works

Architecture overview

<Icon>                      ← Public wrapper
  │
  ├─ preset + variant       → getPresetVariantMerge()   (frozen, stable reference)
  ├─ user props             → arePropsStable() check
  │     ├─ all primitives   → LRU cache (128 entries) — same config = same reference
  │     └─ objects/actions  → direct merge (no cache, but baseProps stays stable)
  │
  ├─ lazy=false (default)   → iconRegistry[name]        (static import, zero latency)
  └─ lazy=true              → getLoadedIcon() || loadIcon() (dynamic import + skeleton)

<IconLazy>                  ← Zero-registry lazy wrapper
  └─ loadIcon(name)         → dynamic import(), no static registry dependency

<IconBase>                  ← SVG renderer
  ├─ receives merged IconProps
  ├─ applies mode (solid / outline / duotone)
  ├─ computes hover color, transitions, animations
  ├─ binds effects action to the <g> layer
  └─ renders <svg> with full a11y attributes

Smart Cache (LRU)

The cache operates in two layers:

  1. Preset/Variant mergegetPresetVariantMerge(preset, variant) returns the exact same frozen object reference for any given combination. Because $derived tracks object identity, this prevents unnecessary re-renders when only the reference changed but the content is identical.

  2. Full props merge (128-entry LRU) — when all user props are primitives (strings, numbers, booleans), a deterministic structural key is built and the result is stored in an LRU cache. The next render with the same config returns the cached reference — Svelte's scheduler sees no change and skips the component update entirely.

    Props containing objects (effects, actions, attrs, parentHoverContext) bypass the global LRU and are merged directly. The preset/variant base remains stable regardless.

This design makes blazir-icons suitable for high-frequency render contexts like data grids, virtualized lists, and real-time dashboards.

Lazy Loading internals

When lazy is omitted (default), the icon component is resolved synchronously from the static registry — no async code, no skeleton, same behavior as a plain import.

When lazy={true}:

  1. Svelte checks getLoadedIcon(name) — a synchronous in-memory cache of already-loaded modules.
  2. If found, renders immediately (zero visible latency on subsequent navigations).
  3. If not found, sets isLoading = true (shows a skeleton placeholder), calls loadIcon(name) (dynamic import()), and updates the component when the module resolves.
  4. If the name prop changes before the load completes, the stale result is discarded — no race conditions.

<IconLazy> — zero-registry alternative

<IconLazy> is a standalone component that never imports the static registry. It only depends on lazy-registry.ts (pure dynamic imports), so bundlers can fully eliminate it from the initial chunk if you only use lazy icons.

<script>
  import { IconLazy } from '@genarou/blazir-icons'
</script>

<!-- No static registry in the bundle at all -->
<IconLazy name="settings" size={24} color="var(--primary)" />

Use <IconLazy> instead of <Icon lazy> when you want to guarantee zero static registry dependency at the module level.

Actions diff bridge

The actions prop accepts an array of [actionFn, params] tuples. On update, the bridge diffs the new array against the previous one:

  • If all action functions are the same references → only update(newParams) is called. Internal state is preserved (e.g. tooltip position, IntersectionObserver).
  • If any function reference changed → destroy() + recreate() for that action.

This is critical for stateful actions like tooltips or lazy-load observers that should not be torn down on every prop change.


Icon Names

Every icon has a direct string name and a typed alias via bzIcons.

<script>
  import { Icon, bzIcons } from '@genarou/blazir-icons'
</script>

<!-- Direct string (plugin can tree-shake this) -->
<Icon name="check" />

<!-- Typed alias — full autocomplete, same result -->
<Icon name={bzIcons.Check} />

Available bzIcons aliases

All 199 icons organized by category.

Navigation & Layout

| Alias | name | |---|---| | bzIcons.Home | home | | bzIcons.Dashboard | dashboard | | bzIcons.DashboardOutline | dashboardOutline | | bzIcons.Settings | settings | | bzIcons.Search | search | | bzIcons.Menu | menu | | bzIcons.Close | close | | bzIcons.Plus | plus | | bzIcons.Copy | copy | | bzIcons.Rocket | rocket | | bzIcons.Sidebar | sidebar | | bzIcons.More | more |

Users & Auth

| Alias | name | |---|---| | bzIcons.User | user | | bzIcons.UserShield | userShield | | bzIcons.UserTie | userTie | | bzIcons.UserPlus | userPlus | | bzIcons.UserMinus | userMinus | | bzIcons.Team | team | | bzIcons.Group | group | | bzIcons.Supervisor | supervisor | | bzIcons.Enterprise | enterprise | | bzIcons.Lock | lock | | bzIcons.LockOpen | lockOpen | | bzIcons.Key | key | | bzIcons.Logout | logout | | bzIcons.Eye | eye | | bzIcons.EyeOff | eyeOff | | bzIcons.Shield | shield | | bzIcons.Fingerprint | fingerprint | | bzIcons.Contact | contact | | bzIcons.Security | security |

Communication

| Alias | name | |---|---| | bzIcons.Email | email | | bzIcons.EmailAnimated | emailAnimated | | bzIcons.Phone | phone | | bzIcons.Bell | bell | | bzIcons.Send | send | | bzIcons.Share | share | | bzIcons.World | world | | bzIcons.Chat | chat | | bzIcons.Link | link |

Business & Finance

| Alias | name | |---|---| | bzIcons.Building | building | | bzIcons.Handshake | handshake | | bzIcons.Money | money | | bzIcons.Wallet | wallet | | bzIcons.Profit | profit | | bzIcons.Safe | safe | | bzIcons.Cost | cost | | bzIcons.Exchange | exchange | | bzIcons.Swap | swap | | bzIcons.Bank | bank | | bzIcons.Pay | pay | | bzIcons.CreditCard | creditCard | | bzIcons.Receipt | receipt | | bzIcons.Buy | buy |

Charts & Data

| Alias | name | |---|---| | bzIcons.Chart | chart | | bzIcons.ChartDocument | chartDocument | | bzIcons.ChartSquare | chartSquare | | bzIcons.ChartDoughnut | chartDoughnut | | bzIcons.Table | table | | bzIcons.List | list | | bzIcons.ListDots | listDots | | bzIcons.ListGroup | listGroup | | bzIcons.TrendingDown | trendingDown | | bzIcons.Database | database | | bzIcons.Server | server |

Files & Documents

| Alias | name | |---|---| | bzIcons.File | file | | bzIcons.Pdf | pdf | | bzIcons.Excel | excel | | bzIcons.ExcelAnimated | excelAnimated | | bzIcons.Word | word | | bzIcons.PowerPoint | powerPoint | | bzIcons.Csv | csv | | bzIcons.Xml | xml | | bzIcons.Zip | zip | | bzIcons.Png | png | | bzIcons.Notes | notes | | bzIcons.Book | book | | bzIcons.Image | image | | bzIcons.ImageAnimated | imageAnimated | | bzIcons.Folder | folder | | bzIcons.FolderShared | folderShared | | bzIcons.Attachment | attachment | | bzIcons.Save | save | | bzIcons.Form | form | | bzIcons.Print | print | | bzIcons.Work | work |

Calendar & Time

| Alias | name | |---|---| | bzIcons.Calendar | calendar | | bzIcons.CalendarPlus | calendarPlus | | bzIcons.CalendarEdit | calendarEdit | | bzIcons.Timer | timer |

Arrows & Navigation

| Alias | name | |---|---| | bzIcons.ArrowRight | arrowRight | | bzIcons.ArrowLeft | arrowLeft | | bzIcons.ArrowUp | arrowUp | | bzIcons.ArrowDown | arrowDown | | bzIcons.ArrowUpDown | arrowUpDown | | bzIcons.ArrowLeftAnimated | arrowLeftAnimated | | bzIcons.ChevronDown | chevronDown | | bzIcons.ChevronUp | chevronUp | | bzIcons.ChevronLeft | chevronLeft | | bzIcons.ChevronRight | chevronRight | | bzIcons.ChevronUpDown | chevronUpDown |

File Actions

| Alias | name | |---|---| | bzIcons.Download | download | | bzIcons.DownloadAnimated | downloadAnimated | | bzIcons.Upload | upload | | bzIcons.UploadAnimated | uploadAnimated | | bzIcons.UploadProgress | uploadProgress | | bzIcons.FileUploadAnimated | fileUploadAnimated | | bzIcons.Refresh | refresh | | bzIcons.SyncPhoto | syncPhoto | | bzIcons.Process | process | | bzIcons.Play | play | | bzIcons.Pause | pause | | bzIcons.Historic | historic | | bzIcons.HardDrive | hardDrive | | bzIcons.Connect | connect | | bzIcons.Archive | archive |

States & Feedback

| Alias | name | |---|---| | bzIcons.Check | check | | bzIcons.CheckOutline | checkOutline | | bzIcons.CheckList | checkList | | bzIcons.CircleCheck | circleCheck | | bzIcons.Error | error | | bzIcons.ErrorOutline | errorOutline | | bzIcons.CircleExclamation | circleExclamation | | bzIcons.CircleExclamationOutline | circleExclamationOutline | | bzIcons.Warning | warning | | bzIcons.CircleInfo | circleInfo | | bzIcons.CircleInfoOutline | circleInfoOutline | | bzIcons.CircleQuestion | circleQuestion | | bzIcons.CircleQuestionOutline | circleQuestionOutline | | bzIcons.Star | star | | bzIcons.Favorites | favorites | | bzIcons.Heart | heart | | bzIcons.Reset | reset | | bzIcons.Height | height | | bzIcons.Alternate | alternate | | bzIcons.Moon | moon | | bzIcons.Sun | sun | | bzIcons.Colors | colors |

Loading & Progress

| Alias | name | |---|---| | bzIcons.SpinnerDots | spinnerDots | | bzIcons.Spinner | spinner |

Commerce & Sales

| Alias | name | |---|---| | bzIcons.Product | product | | bzIcons.Bag | bag | | bzIcons.POS | pos | | bzIcons.Category | category | | bzIcons.CategoryAdd | categoryAdd | | bzIcons.CategorySearch | categorySearch | | bzIcons.BoxAdd | boxAdd | | bzIcons.Measure | measure | | bzIcons.Box | box | | bzIcons.Scan | scan | | bzIcons.Cart | cart | | bzIcons.Cards | cards | | bzIcons.Percentage | percentage | | bzIcons.Gift | gift |

Logistics & Transport

| Alias | name | |---|---| | bzIcons.Truck | truck | | bzIcons.TruckReturn | truckReturn | | bzIcons.Warehouse | warehouse | | bzIcons.Location | location | | bzIcons.LocationAnimated | locationAnimated |

Tools & Utilities

| Alias | name | |---|---| | bzIcons.AI | ai | | bzIcons.Edit | edit | | bzIcons.EditOutline | editOutline | | bzIcons.Trash | trash | | bzIcons.TrashOutline | trashOutline | | bzIcons.Filter | filter | | bzIcons.FilterOutline | filterOutline | | bzIcons.Tags | tags | | bzIcons.Tools | tools | | bzIcons.ObjectGroup | objectGroup | | bzIcons.Project | project |

Common Actions

| Alias | name | |---|---| | bzIcons.ExternalLink | externalLink | | bzIcons.Maximize | maximize | | bzIcons.Minimize | minimize | | bzIcons.Undo | undo | | bzIcons.Redo | redo | | bzIcons.Grip | grip |

Layout

| Alias | name | |---|---| | bzIcons.Grid | grid | | bzIcons.Layers | layers | | bzIcons.Sliders | sliders |

Media & Devices

| Alias | name | |---|---| | bzIcons.Camera | camera | | bzIcons.Desktop | desktop | | bzIcons.Video | video | | bzIcons.Microphone | microphone | | bzIcons.MicOff | micOff | | bzIcons.Volume | volume | | bzIcons.VolumeOff | volumeOff | | bzIcons.Wifi | wifi | | bzIcons.Power | power |

Dev

| Alias | name | |---|---| | bzIcons.Code | code | | bzIcons.Terminal | terminal |

Cloud

| Alias | name | |---|---| | bzIcons.CloudAlert | cloudAlert | | bzIcons.CloudCheck | cloudCheck | | bzIcons.CloudDownload | cloudDownload | | bzIcons.CloudUpload | cloudUpload |

Other

| Alias | name | |---|---| | bzIcons.Blaze | blaze | | bzIcons.Earth | earth | | bzIcons.Globe | globe | | bzIcons.LightHub | lightHub | | bzIcons.Qr | qr | | bzIcons.Sync | sync |


Props Reference

All props are optional. Every prop can be passed to <Icon>, <IconLazy>, or <IconBase>.

Visual

| Prop | Type | Default | Description | |---|---|---|---| | name | IconName | — | Icon identifier | | size | number \| string | 24 | Width and height. Accepts px, rem, em, token (sm, md, lg, etc.) or a plain number | | color | string | currentColor | Fill or stroke color | | stroke | string | — | Explicit stroke color (overrides color for stroke) | | strokeWidth | number \| string | — | SVG stroke width | | strokeLinecap | "round" \| "butt" \| "square" | — | SVG stroke-linecap attribute | | strokeLinejoin | "round" \| "miter" \| "bevel" | — | SVG stroke-linejoin attribute | | fill | string | — | Explicit fill color | | mode | "solid" \| "outline" \| "duotone" | "solid" | Rendering mode | | viewBox | string | "0 0 24 24" | SVG viewBox attribute | | preserveAspectRatio | string | — | SVG preserveAspectRatio attribute | | class | string | — | CSS class on the wrapper element | | className | string | — | Alias for class | | style | string | — | Inline style on the wrapper element | | attrs | Record<string, any> | — | Arbitrary extra attributes forwarded to the <svg> element |

Size Tokens

| Token | Value | |---|---| | xs | 12px | | sm | 16px | | md | 20px | | lg | 24px | | xl | 32px | | 2xl | 40px | | 3xl | 48px |

<Icon name="check" size="sm" />
<Icon name="check" size={32} />
<Icon name="check" size="1.5rem" />

Transform

| Prop | Type | Default | Description | |---|---|---|---| | rotate | number \| string | — | Rotation in degrees or CSS string | | flipH | boolean | false | Flip horizontally | | flipV | boolean | false | Flip vertically | | nonScalingStroke | boolean | false | Keep stroke width fixed regardless of transform |

<Icon name="arrowRight" rotate={45} />
<Icon name="arrowRight" flipH />
<Icon name="arrowRight" rotate={90} flipV />

Animations

| Prop | Type | Default | Description | |---|---|---|---| | spin | boolean \| number \| string | false | Continuous rotation. true = 1s linear, number = duration in ms | | pulse | boolean | false | Opacity + scale pulse | | bounce | boolean | false | Vertical bounce | | wiggle | boolean | false | Left-right rotation wiggle | | heartbeat | boolean | false | Double-pulse heartbeat effect | | elastic | boolean | false | Elastic scale pop | | animationDuration | number \| string | — | Override animation duration (400, "400ms", "0.4s") | | animationDelay | number \| string | — | Animation start delay | | animationEasing | string | — | CSS easing function |

<Icon name="spinnerDots" spin />
<Icon name="spinnerDots" spin={800} />
<Icon name="bell" bounce animationDuration={600} />
<Icon name="heart" heartbeat animationDelay="200ms" />
<Icon name="star" pulse animationEasing="ease-in-out" />

Entry Transitions

| Prop | Type | Description | |---|---|---| | scaleIn | boolean | Animate in with a scale effect | | fadeIn | boolean | Animate in with a fade effect | | slideIn | boolean | Animate in with a slide effect | | slideDirection | "up" \| "down" \| "left" \| "right" | Direction for slideIn | | morphTo | "play" \| "pause" \| "menu" \| "close" \| "arrow" \| "check" | Morph the icon shape to a target state | | chevronState | "open" \| "closed" \| "up" \| "down" \| "left" \| "right" | Rotate a chevron icon to indicate state | | chevronOpen | boolean | Shorthand: true = chevronState="open" |

<!-- Animated menu toggle -->
<Icon name="menu" morphTo={isOpen ? 'close' : 'menu'} />

<!-- Animated accordion chevron -->
<Icon name="chevronDown" chevronOpen={isExpanded} />

<!-- Entry animations -->
<Icon name="check" scaleIn />
<Icon name="warning" fadeIn />
<Icon name="bell" slideIn slideDirection="down" />

Interaction

| Prop | Type | Default | Description | |---|---|---|---| | hoverColor | string | — | Color applied on hover | | activeColor | string | — | Color applied on press/active | | disabled | boolean | false | Reduces opacity to 0.4 and disables all pointer events | | loading | boolean | false | Replaces the icon with a spinning circle until false | | tooltip | string | — | Native browser tooltip | | hoverSpeed | "instant" \| "fast" \| "normal" \| "slow" \| "sluggish" | "normal" | Semantic preset for hover transition speed | | transitionMs | number \| string | 250 | Exact hover transition duration. Overrides hoverSpeed | | transitionEasing | string | "ease" | CSS easing for hover transition | | parentHoverContext | { hovered: boolean } | — | Trigger hover state from a parent element |

hoverSpeed presets

| Value | Duration | |---|---| | "instant" | 0ms | | "fast" | 120ms | | "normal" | 250ms ← default | | "slow" | 400ms | | "sluggish" | 600ms |

<Icon name="edit" hoverColor="var(--primary)" hoverSpeed="fast" />
<Icon name="heart" hoverColor="#f97316" activeColor="#dc2626" />
<Icon name="send" disabled />
<Icon name="save" loading={isSaving} />
<Icon name="circleInfo" tooltip="More information" />

<!-- Trigger icon hover when parent row is hovered -->
<script>
  let hovered = $state(false)
  const ctx = $derived({ hovered })
</script>
<tr onmouseenter={() => hovered = true} onmouseleave={() => hovered = false}>
  <td><Icon name="edit" parentHoverContext={ctx} hoverColor="var(--primary)" /></td>
</tr>

Compact Mode

| Prop | Type | Default | Description | |---|---|---|---| | compact | "off" \| "auto" \| "outline" \| "duotone" | "off" | Compact rendering mode | | compactSizeThreshold | number | 20 | Size in px below which compact activates (when "auto") | | compactFillOpacity | number | 0.15 | Fill opacity in compact mode | | compactStrokeWidth | number \| string | — | Stroke width in compact mode |

<Icon name="user" compact="auto" size={16} />
<Icon name="folder" compact="duotone" compactFillOpacity={0.2} />

Accessibility

| Prop | Type | Default | Description | |---|---|---|---| | ariaLabel | string | Icon name | aria-label on the SVG | | title | string | — | SVG <title> element | | titleId | string | — | id for the <title> element | | decorative | boolean | false | Sets aria-hidden="true" | | testId | string | — | data-testid attribute |

<button>
  <Icon name="download" decorative />
  Download
</button>

<Icon name="check" ariaLabel="Task completed" />

Lazy Loading Prop

| Prop | Type | Default | Description | |---|---|---|---| | lazy | boolean | false | Load the icon via dynamic import, enabling per-icon code splitting |

<!-- Eager (default) -->
<Icon name="check" />

<!-- Lazy — separate chunk, skeleton while loading -->
<Icon name="check" lazy />

Presets

Presets apply a predefined set of props in one shot.

<Icon name="check" preset="success" />
<Icon name="home"  preset="nav" />
<Icon name="plus"  preset="button" />

| Preset | Properties | |---|---| | primary | color: var(--primary), hoverColor: var(--primary-hover) | | secondary | color: var(--secondary), hoverColor: var(--secondary-foreground) | | accent | color: var(--accent-color), hoverColor: var(--accent-hover) | | success | color: var(--success-color), hoverColor: var(--success-hover) | | warning | color: var(--warning-color), hoverColor: var(--warning-hover) | | danger | color: var(--danger-color), hoverColor: var(--danger-hover) | | muted | color: var(--icon-fg, var(--ui-muted-fg)), hover → foreground | | nav | size: 24, nav colors, subtle scale on hover | | sidebar | size: 18, sidebar colors, scale on hover | | button | size: 20, currentColor, cursor pointer, scale on hover | | badge | size: 16, compact auto | | hero | size: 48, primary color, bounce on hover | | loading | spin: true, size: 24, primary color |

Props passed directly always override preset values.

<Icon name="check" preset="nav" size={32} />
<Icon name="trash" preset="button" variant="danger" />

Variants

Variants apply a color scheme without touching size or behavior.

| Variant | Color token | |---|---| | primary | var(--primary) | | secondary | var(--secondary) | | accent | var(--accent-color) | | success | var(--success-color) | | warning | var(--warning-color) | | danger | var(--danger-color) | | muted | var(--icon-fg, var(--ui-muted-fg)) | | ghost | var(--ui-muted-fg) |


Lazy Loading

By default icons load eagerly (zero latency, no skeletons). Add lazy to defer loading and enable per-icon code splitting.

<!-- Eager (default) -->
<Icon name="check" />

<!-- Lazy — loaded on first render, skeleton shown while loading -->
<Icon name="check" lazy />

<!-- Zero-registry component — no static imports whatsoever -->
<IconLazy name="check" />

Manual preload

import { preloadIcons } from '@genarou/blazir-icons'

// Runs in background via requestIdleCallback
preloadIcons(['check', 'home', 'settings', 'user'])

Programmatic load

import { loadIcon, getLoadedIcon } from '@genarou/blazir-icons'

const Check = await loadIcon('check')       // async load + cache
const Cached = getLoadedIcon('check')       // sync lookup (null if not yet loaded)

Effects System

Declarative interactive effects applied via the effects prop. All effects respect prefers-reduced-motion.

<Icon name="settings" effects={{ spinOnHover: true, cursor: 'pointer' }} />
<Icon name="trash"    effects={{ wiggleOnHover: true, elasticOnClick: true }} />
<Icon name="heart"    effects={{ heartbeatOnHover: true, hoverScale: 1.15 }} />

IconEffectOptions

| Option | Type | Description | |---|---|---| | spinOnHover | boolean | Spin on mouse enter | | bounceOnHover | boolean | Bounce on mouse enter | | wiggleOnHover | boolean | Wiggle on mouse enter | | heartbeatOnHover | boolean | Heartbeat on hover | | heartbeatOnActive | boolean | Heartbeat on mousedown | | slideOnHover | "up" \| "down" \| "left" \| "right" | Slide translate on hover | | elasticOnClick | boolean | Elastic scale pop on click | | hoverScale | number | Scale factor on hover (1.1 = 110%) | | pressScale | number | Scale factor on press | | rotateOnHover | number | Degrees to rotate on hover | | transitionMs | number | Transition duration in ms | | easing | string | CSS easing function | | cursor | string | CSS cursor on hover | | tooltip | string | Native title tooltip | | focusRing | boolean | Show visible focus ring |

Using iconEffects as a Svelte action

<script>
  import { iconEffects } from '@genarou/blazir-icons'
</script>

<button use:iconEffects={{ spinOnHover: true, hoverScale: 1.1 }}>
  Click me
</button>

Actions System

Pass Svelte actions to the icon wrapper via the actions prop. Actions are diffed on update — state is preserved when params change.

<script>
  import { Icon } from '@genarou/blazir-icons'
  import { tooltip } from '$lib/actions/tooltip'
  import { lazyLoad } from '$lib/actions/lazy'

  let opts = $state({ text: 'Save file' })
</script>

<Icon name="save" actions={[[tooltip, opts], [lazyLoad]]} />

Each entry is a tuple [actionFn, params?]. When params change, update() is called. When the action function itself changes, the action is destroyed and recreated.


IconBadge

<script>
  import { IconBadge } from '@genarou/blazir-icons'
</script>

<IconBadge name="bell" badge />                                    <!-- dot -->
<IconBadge name="bell" badge={5} />                                <!-- count -->
<IconBadge name="chat" badge="!" />                                <!-- text -->
<IconBadge name="bell" badge={12} badgeColor="#f59e0b" badgeSize={18} />
<IconBadge name="bell" badge={3} badgePosition="top-left" />

IconBadge props

Accepts all Icon props plus:

| Prop | Type | Default | Description | |---|---|---|---| | badge | boolean \| number \| string | — | true = dot · number/string = label | | badgeColor | string | #ef4444 | Badge background color | | badgeTextColor | string | #ffffff | Badge text color | | badgeSize | number | 8 (dot) / 16 (label) | Badge diameter in px | | badgePosition | "top-right" \| "top-left" \| "bottom-right" \| "bottom-left" | "top-right" | Corner placement |

badge={false} or omitting badge renders the icon directly without any wrapper — no DOM overhead.


CustomIcon

Render any custom SVG string using the same IconBase engine.

<script>
  import { CustomIcon } from '@genarou/blazir-icons'

  const logoSvg = `<path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/>`
</script>

<CustomIcon svgContent={logoSvg} size={32} color="var(--primary)" />
<CustomIcon svgContent={logoSvg} hoverColor="#6366f1" effects={{ hoverScale: 1.1 }} />
<CustomIcon svgContent={logoSvg} viewBox="0 0 48 48" size={48} />

| Prop | Type | Default | Description | |---|---|---|---| | svgContent | string | required | Raw SVG inner markup (not the <svg> tag itself) | | viewBox | string | "0 0 24 24" | ViewBox for the SVG container | | + all IconProps | | | Every prop from Icon is supported |


Vite Plugin (Tree Shaking)

The plugin scans your source files at build time, detects static name="..." values, and generates a minimal registry containing only the icons you use.

// vite.config.ts
import { blazirIconsPlugin } from '@genarou/blazir-icons/plugin'
import { svelte } from '@sveltejs/vite-plugin-svelte'

export default {
  plugins: [
    blazirIconsPlugin(),
    svelte(),
  ]
}
<!-- Detected → only Check.svelte bundled -->
<Icon name="check" />
<Icon name={"home"} />

<!-- Dynamic → falls back to full registry (safe) -->
<Icon name={someVariable} />

Plugin Options

blazirIconsPlugin({
  root: './src',
  extensions: ['.svelte', '.ts', '.tsx', '.js', '.jsx'],
})

Bundle size comparison

| Scenario | Bundle (gzip) | |---|---| | No plugin — all 199 icons | ~12 KB | | With plugin — 10 static icons | ~1–2 KB | | Direct named imports — zero plugin needed | only imported icons |


Direct Icon Imports

Three ways to import icons with full tree shaking, no plugin required:

// 1. Named exports from the main package
import { CircleCheck, Home, Settings } from '@genarou/blazir-icons'

// 2. Named exports from the /components barrel (identical result, explicit path)
import { CircleCheck, Home } from '@genarou/blazir-icons/components'

// 3. Individual file (maximum isolation)
import CircleCheck from '@genarou/blazir-icons/icons/CircleCheck'
import Home        from '@genarou/blazir-icons/icons/Home'

Use them as regular Svelte components. All IconProps are supported.

<CircleCheck size={20} color="var(--success-color)" />
<Home size={24} hoverColor="var(--primary)" />

TypeScript

import type { IconProps, IconName, IconMode } from '@genarou/blazir-icons'
import type { IconEffectOptions }             from '@genarou/blazir-icons'
import type { BzIconKey }                     from '@genarou/blazir-icons'

const icon: IconName = 'check'

const effects: IconEffectOptions = {
  spinOnHover: true,
  hoverScale: 1.1,
}

const key: BzIconKey = 'Check'

Extending the registry

import { iconRegistry } from '@genarou/blazir-icons'

type MyIconName = keyof typeof iconRegistry

CSS Custom Properties

| Variable | Default | Description | |---|---|---| | --bz-icon-bounce-amt | 18% | Bounce height | | --bz-icon-pulse-scale | 1.04 | Pulse scale factor | | --bz-icon-ring | primary | Focus ring color | | --bz-icon-wiggle-angle | 3deg | Wiggle rotation amount | | --bz-icon-slide-distance | 8px | Slide effect distance |

:root {
  --bz-icon-bounce-amt: 24%;
  --bz-icon-wiggle-angle: 5deg;
}

Accessibility Guide

<!-- Decorative icon next to a labeled button -->
<button>
  <Icon name="trash" decorative />
  Delete item
</button>

<!-- Standalone meaningful icon -->
<Icon name="warning" ariaLabel="Warning: unsaved changes" />

<!-- With visible tooltip -->
<Icon name="circleInfo" title="More information" ariaLabel="More information" />

<!-- In a labeled group -->
<div aria-label="Status">
  <Icon name="circleCheck" decorative />
  <span>All systems operational</span>
</div>

Real-World Examples

Sidebar navigation item

<script>
  import { Icon } from '@genarou/blazir-icons'
  let { active = false, label = '', icon = 'home' } = $props()
</script>

<a class="nav-item" class:active>
  <Icon name={icon} preset="sidebar" color={active ? 'var(--primary)' : undefined} effects={{ hoverScale: 1.08 }} decorative />
  <span>{label}</span>
</a>

Loading button

<script>
  import { Icon } from '@genarou/blazir-icons'
  let saving = $state(false)

  async function submit() {
    saving = true
    await doWork()
    saving = false
  }
</script>

<button onclick={submit} disabled={saving}>
  <Icon name="save" loading={saving} decorative />
  {saving ? 'Saving...' : 'Save'}
</button>

Animated accordion chevron

<script>
  import { Icon } from '@genarou/blazir-icons'
  let open = $state(false)
</script>

<button onclick={() => open = !open}>
  Details
  <Icon name="chevronRight" chevronOpen={open} preset="muted" decorative />
</button>

Password visibility toggle

<script>
  import { Icon } from '@genarou/blazir-icons'
  let visible = $state(false)
</script>

<div class="input-wrapper">
  <input type={visible ? 'text' : 'password'} />
  <button onclick={() => visible = !visible} aria-label={visible ? 'Hide password' : 'Show password'}>
    <Icon name={visible ? 'eyeOff' : 'eye'} preset="muted" effects={{ hoverScale: 1.1, cursor: 'pointer' }} decorative />
  </button>
</div>

Notification bell with badge

<script>
  import { IconBadge } from '@genarou/blazir-icons'
  let count = $state(0)
</script>

<button aria-label="Notifications ({count} unread)">
  <IconBadge name="bell" size={22} badge={count > 0 ? count : false} effects={{ wiggleOnHover: true, cursor: 'pointer' }} decorative />
</button>

Table row with hover-revealed actions

<script>
  import { Icon } from '@genarou/blazir-icons'
  let hovered = $state(false)
  const ctx = $derived({ hovered })
</script>

<tr onmouseenter={() => hovered = true} onmouseleave={() => hovered = false}>
  <td>{row.name}</td>
  <td class="actions">
    <Icon name="edit"  parentHoverContext={ctx} hoverColor="var(--primary)"     preset="button" ariaLabel="Edit row" />
    <Icon name="trash" parentHoverContext={ctx} hoverColor="var(--danger-color)" preset="button" ariaLabel="Delete row" />
  </td>
</tr>

Dynamic status icon

<script>
  import { Icon } from '@genarou/blazir-icons'
  import type { IconName } from '@genarou/blazir-icons'

  type Status = 'success' | 'warning' | 'error' | 'loading'

  const iconMap: Record<Status, IconName> = {
    success: 'circleCheck',
    warning: 'warning',
    error:   'error',
    loading: 'spinnerDots',
  }

  let { status }: { status: Status } = $props()
</script>

<Icon name={iconMap[status]} variant={status === 'loading' ? 'muted' : status} spin={status === 'loading'} size={18} ariaLabel="Status: {status}" />

Preloading icons on route change (SvelteKit)

// src/routes/dashboard/+page.ts
import { preloadIcons } from '@genarou/blazir-icons'

export const load = async () => {
  preloadIcons(['chart', 'table', 'user', 'settings', 'logout', 'bell'])
  return {}
}

Custom element with effects action

<script>
  import { iconEffects } from '@genarou/blazir-icons'
  import { CircleCheck } from '@genarou/blazir-icons'
</script>

<div class="status-chip" use:iconEffects={{ pulse: true, hoverScale: 1.05, cursor: 'pointer' }}>
  <CircleCheck size={14} color="var(--success-color)" decorative />
  Active
</div>