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.3.2

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.

  • 163 icons — original SVG artwork
  • Svelte 5 runes$props, $derived, $effect
  • 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)

<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.

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 163 icons organized by category. Use the alias for TypeScript autocomplete or the name as a plain string.

Navigation & Layout

| Alias | name | |---|---| | bzIcons.Home | home | | bzIcons.Dashboard | dashboard | | bzIcons.DashboardOutline | dashboardOutline | | bzIcons.Settings | settings | | bzIcons.Search | search | | bzIcons.Filter | filter | | 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.UserTie | userTie | | 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 |

Calendar & Time

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

Arrows & Navigation

| Alias | name | |---|---| | bzIcons.ArrowRight | arrowRight | | bzIcons.ArrowUp | arrowUp | | bzIcons.ArrowUpDown | arrowUpDown | | bzIcons.ArrowLeftAnimated | arrowLeftAnimated | | bzIcons.ChevronDown | chevronDown | | 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 |

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 |

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.Tags | tags | | bzIcons.Tools | tools | | bzIcons.ObjectGroup | objectGroup | | bzIcons.Project | project |

Media & Devices

| Alias | name | |---|---| | bzIcons.Camera | camera | | bzIcons.Desktop | desktop | | bzIcons.Wifi | wifi | | bzIcons.Power | power |

Cloud

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

Other

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


Props Reference

All props are optional. Every prop can be passed to <Icon> 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 (excluding width/height) |

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 (vector-effect="non-scaling-stroke") |

<Icon name="arrow" rotate={45} />
<Icon name="arrow" flipH />
<Icon name="arrow" 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="loadingDots" spin />
<Icon name="loadingDots" spin={800} />
<Icon name="bell" bounce animationDuration={600} />
<Icon name="heart" heartbeat animationDelay="200ms" />
<Icon name="star" pulse animationEasing="ease-in-out" />

<!-- Combine multiple animations -->
<Icon name="loadingRegular" spin pulse />

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="hamburguer" 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. Priority: activeColor > hoverColor > color | | disabled | boolean | false | Reduces opacity to 0.4 and disables all pointer events and hover effects | | loading | boolean | false | Replaces the icon with a spinning circle until false. Reuses internal spin keyframe — zero extra weight | | tooltip | string | — | Native browser tooltip. Shorthand for effects={{ 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 |

<!-- Hover color with speed preset -->
<Icon name="edit" hoverColor="var(--primary)" hoverSpeed="fast" />

<!-- Active/press color -->
<Icon name="heart" hoverColor="#f97316" activeColor="#dc2626" />

<!-- Disabled state -->
<Icon name="send" disabled />
<Icon name="save" disabled={!isFormValid} />

<!-- Loading state — auto spinner, no wrapper needed -->
<Icon name="save" loading={isSaving} />

<!-- Tooltip -->
<Icon name="info" tooltip="More information" />

<!-- Custom easing -->
<Icon name="bell" hoverColor="var(--primary)" transitionMs={350} transitionEasing="ease-in-out" />

<!-- 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

Reduces visual weight of solid icons at small sizes by adjusting opacity.

| 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 |

<!-- Auto: switches to outline style below 20px -->
<Icon name="user" compact="auto" size={16} />

<!-- Always compact duotone -->
<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 (tooltip on hover in browsers) | | titleId | string | — | id for the <title> element (for aria-labelledby) | | decorative | boolean | false | Sets aria-hidden="true" — use when icon is purely decorative | | testId | string | — | data-testid attribute |

<!-- Decorative icon next to a labeled button -->
<button>
  <Icon name="download" decorative />
  Download
</button>

<!-- Standalone meaningful icon -->
<Icon name="check" ariaLabel="Task completed" />

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

Lazy Loading Prop

| Prop | Type | Default | Description | |---|---|---|---| | lazy | boolean | false | Load the icon as a separate dynamic import, enabling per-icon code splitting. Shows a skeleton placeholder while loading. |

<!-- Eager (default) — bundled with registry -->
<Icon name="check" />

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

Presets

Presets apply a predefined set of props in one shot. Define colors, sizes, and behaviors using your CSS design tokens.

<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.

<!-- preset sets size=24, but size={32} wins -->
<Icon name="check" preset="nav" size={32} />

<!-- preset + variant combination -->
<Icon name="trash" preset="button" variant="danger" />

Variants

Variants apply a color scheme without touching size or behavior. Combine with presets for full control.

<Icon name="check" preset="button" variant="success" />

| 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) — same bundle chunk as always -->
<Icon name="check" />

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

Manual preload

Preload a set of icons before they are needed (e.g. on route anticipation):

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'

// Async load + cache
const Check = await loadIcon('check')

// Synchronous lookup (returns null if not yet loaded)
const Cached = getLoadedIcon('check')

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 | | slideOnHover | "up" \| "down" \| "left" \| "right" | Slide translate on hover | | morphOnHover | "play" \| "pause" \| "menu" \| "close" \| "arrow" \| "check" | Morph shape on hover | | elasticOnClick | boolean | Elastic scale pop on click | | heartbeatOnActive | boolean | Heartbeat on mousedown | | heartbeatOnHover | boolean | Heartbeat on hover | | pulse | boolean | Continuous pulse | | 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 | | kbFocusAttr | string | Data attribute set on keyboard focus |

Using iconEffects as a Svelte action

For advanced cases where you need to apply effects to a custom element:

<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 in actions is a tuple [actionFn, params?]. When params change, update() is called. When the action function itself changes, the action is destroyed and recreated.


IconBadge

IconBadge wraps any icon with an absolute-positioned notification badge. Zero weight unless imported.

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

<!-- Dot (boolean) -->
<IconBadge name="bell" badge />

<!-- Count -->
<IconBadge name="bell" badge={5} />

<!-- Text -->
<IconBadge name="chat" badge="!" />

<!-- Custom color and size -->
<IconBadge name="bell" badge={12} badgeColor="#f59e0b" badgeSize={18} />

<!-- Position (default: top-right) -->
<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 | | 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 element — no DOM overhead.


CustomIcon

Render any custom SVG string using the same IconBase engine — all effects, transitions, hover colors, animations and a11y props work out of the box.

<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>

<!-- Same API as Icon — all props supported -->
<CustomIcon svgContent={logoSvg} size={32} color="var(--primary)" />

<!-- With hover and effects -->
<CustomIcon
  svgContent={logoSvg}
  hoverColor="#6366f1"
  hoverSpeed="fast"
  effects={{ hoverScale: 1.1 }}
/>

<!-- With animations -->
<CustomIcon svgContent={logoSvg} spin pulse />

<!-- Custom viewBox for non-24x24 SVGs -->
<CustomIcon svgContent={logoSvg} viewBox="0 0 48 48" size={48} />

CustomIcon props

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

The content is rendered via {@html}. For static svgContent (most common case) the cost is a single innerHTML assignment at mount — identical to any other icon. All IconBase effects run on the containing <g> layer.


Vite Plugin (Tree Shaking)

Without the plugin, all 152 icons are included in your bundle. With the plugin, only the icons you statically reference are bundled.

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

export default {
  plugins: [
    blazirIconsPlugin(),
    svelte(),
  ]
}

The plugin scans your source files at build time, detects static name="..." values, and generates a minimal registry.

<!-- Detected statically → only Check.svelte in bundle -->
<Icon name="check" />

<!-- Also detected statically -->
<Icon name={"home"} />

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

Plugin Options

blazirIconsPlugin({
  // Root directory to scan. Default: Vite's config.root
  root: './src',

  // File extensions to include in scan
  extensions: ['.svelte', '.ts', '.tsx', '.js', '.jsx'],
})

Bundle size comparison

| Scenario | Bundle (gzip) | |---|---| | No plugin — all 163 icons | ~11 KB | | With plugin — 10 static icons | ~1–2 KB | | With plugin — dynamic names detected | ~11 KB (safe fallback) |


Direct Icon Imports

Import a single icon component directly for maximum tree shaking without the plugin:

import Check    from '@genarou/blazir-icons/icons/Check'
import Home     from '@genarou/blazir-icons/icons/Home'
import Settings from '@genarou/blazir-icons/icons/Settings'

Use them as regular Svelte components. All IconProps are supported, but presets and variants are not applied automatically.

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

TypeScript

Full type coverage on all props and icon names.

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

// Typed icon name
const icon: IconName = 'check'

// Typed effect options
const effects: IconEffectOptions = {
  spinOnHover: true,
  hoverScale: 1.1,
}

// Typed bzIcons alias
const key: BzIconKey = 'Check'

Extending the registry

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

// Autocomplete on all registry keys
type MyIconName = keyof typeof iconRegistry

CSS Custom Properties

Customize animations globally via CSS variables.

| 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 | | --bz-icon-size | set by component | Icon size (set automatically) |

/* globals.css */
:root {
  --bz-icon-bounce-amt: 24%;
  --bz-icon-wiggle-angle: 5deg;
}

Accessibility Guide

<!-- Decorative icon — hidden from screen readers -->
<button>
  <Icon name="trash" decorative />
  Delete item
</button>

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

<!-- With visible tooltip -->
<Icon name="info" 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'
  export let active = false
  export let label = ''
  export let icon = 'home'
</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>

<!-- The icon swaps to a spinner automatically while saving -->
<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: 'loadingDots',
  }

  export let status: Status = 'loading'
</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 () => {
  // Icons are prefetched in background while page data loads
  preloadIcons(['chart', 'table', 'user', 'settings', 'logout', 'bell'])
  return {}
}

Custom element with effects action

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

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