@genarou/blazir-icons 1.2.20 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +121 -0
- package/README.md +1206 -0
- package/dist/CustomIcon.svelte +30 -0
- package/dist/CustomIcon.svelte.d.ts +14 -0
- package/dist/Icon.svelte +282 -102
- package/dist/Icon.svelte.d.ts +12 -5
- package/dist/IconBadge.svelte +75 -0
- package/dist/IconBadge.svelte.d.ts +16 -0
- package/dist/IconBase.svelte +89 -57
- package/dist/effects.js +1 -3
- package/dist/icons/Camera.svelte +19 -0
- package/dist/icons/Camera.svelte.d.ts +4 -0
- package/dist/icons/Cards.svelte +19 -0
- package/dist/icons/Cards.svelte.d.ts +4 -0
- package/dist/icons/CloudAlert.svelte +19 -0
- package/dist/icons/CloudAlert.svelte.d.ts +4 -0
- package/dist/icons/CloudCheck.svelte +19 -0
- package/dist/icons/CloudCheck.svelte.d.ts +4 -0
- package/dist/icons/CloudDownload.svelte +19 -0
- package/dist/icons/CloudDownload.svelte.d.ts +4 -0
- package/dist/icons/CreditCard.svelte +19 -0
- package/dist/icons/CreditCard.svelte.d.ts +4 -0
- package/dist/icons/Desktop.svelte +19 -0
- package/dist/icons/Desktop.svelte.d.ts +4 -0
- package/dist/icons/DoughnutChart.svelte +19 -0
- package/dist/icons/DoughnutChart.svelte.d.ts +4 -0
- package/dist/icons/Earth.svelte +19 -0
- package/dist/icons/Earth.svelte.d.ts +4 -0
- package/dist/icons/Globe.svelte +19 -0
- package/dist/icons/Globe.svelte.d.ts +4 -0
- package/dist/icons/LightHub.svelte +19 -0
- package/dist/icons/LightHub.svelte.d.ts +4 -0
- package/dist/icons/Link.svelte +19 -0
- package/dist/icons/Link.svelte.d.ts +4 -0
- package/dist/icons/Power.svelte +19 -0
- package/dist/icons/Power.svelte.d.ts +4 -0
- package/dist/icons/Receipt.svelte +19 -0
- package/dist/icons/Receipt.svelte.d.ts +4 -0
- package/dist/icons/Sync.svelte +19 -0
- package/dist/icons/Sync.svelte.d.ts +4 -0
- package/dist/icons/Upload.svelte +12 -57
- package/dist/icons/Wifi.svelte +19 -0
- package/dist/icons/Wifi.svelte.d.ts +4 -0
- package/dist/icons/lazy-registry.d.ts +21 -0
- package/dist/icons/lazy-registry.js +251 -0
- package/dist/icons/registry.d.ts +145 -134
- package/dist/icons/registry.js +177 -137
- package/dist/icons-api.d.ts +65 -267
- package/dist/icons-api.js +82 -465
- package/dist/index.d.ts +5 -5
- package/dist/index.js +14 -11
- package/dist/plugin/index.d.ts +46 -0
- package/dist/plugin/index.js +327 -0
- package/dist/smart-cache.d.ts +35 -0
- package/dist/smart-cache.js +192 -0
- package/dist/types.d.ts +19 -2
- package/dist/utils/sanitize.d.ts +25 -0
- package/dist/utils/sanitize.js +109 -0
- package/package.json +23 -13
- package/dist/icons/Aws.svelte +0 -19
- package/dist/icons/Aws.svelte.d.ts +0 -4
- package/dist/icons/Facebook.svelte +0 -18
- package/dist/icons/Facebook.svelte.d.ts +0 -4
- package/dist/icons/Golang.svelte +0 -17
- package/dist/icons/Golang.svelte.d.ts +0 -4
- package/dist/icons/Google.svelte +0 -18
- package/dist/icons/Google.svelte.d.ts +0 -4
- package/dist/icons/Paypal.svelte +0 -21
- package/dist/icons/Paypal.svelte.d.ts +0 -4
package/README.md
ADDED
|
@@ -0,0 +1,1206 @@
|
|
|
1
|
+
# blazir-icons
|
|
2
|
+
|
|
3
|
+
A high-performance Svelte 5 icon library with smart caching, lazy loading, presets, variants, and a declarative effects system.
|
|
4
|
+
|
|
5
|
+
- **163 icons** — original SVG artwork
|
|
6
|
+
- **Svelte 5 runes** — `$props`, `$derived`, `$effect`
|
|
7
|
+
- **Smart LRU cache** — referential stability, zero re-renders on stable props
|
|
8
|
+
- **Lazy loading** — per-icon code splitting via `import()`
|
|
9
|
+
- **Vite plugin** — automatic tree shaking, only used icons in the bundle
|
|
10
|
+
- **Full TypeScript** — autocomplete on every prop, icon name, preset, and variant
|
|
11
|
+
- **Accessible** — `aria-label`, `title`, `decorative` support out of the box
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Table of Contents
|
|
16
|
+
|
|
17
|
+
- [Installation](#installation)
|
|
18
|
+
- [Quick Start](#quick-start)
|
|
19
|
+
- [How It Works](#how-it-works)
|
|
20
|
+
- [Icon Names](#icon-names)
|
|
21
|
+
- [Props Reference](#props-reference)
|
|
22
|
+
- [Presets](#presets)
|
|
23
|
+
- [Variants](#variants)
|
|
24
|
+
- [Lazy Loading](#lazy-loading)
|
|
25
|
+
- [Effects System](#effects-system)
|
|
26
|
+
- [Actions System](#actions-system)
|
|
27
|
+
- [IconBadge](#iconbadge)
|
|
28
|
+
- [CustomIcon](#customicon)
|
|
29
|
+
- [Vite Plugin (Tree Shaking)](#vite-plugin-tree-shaking)
|
|
30
|
+
- [Direct Icon Imports](#direct-icon-imports)
|
|
31
|
+
- [TypeScript](#typescript)
|
|
32
|
+
- [CSS Custom Properties](#css-custom-properties)
|
|
33
|
+
- [Accessibility Guide](#accessibility-guide)
|
|
34
|
+
- [Real-World Examples](#real-world-examples)
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install @genarou/blazir-icons
|
|
42
|
+
# or
|
|
43
|
+
pnpm add @genarou/blazir-icons
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Peer dependency:** Svelte 5
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
```svelte
|
|
53
|
+
<script>
|
|
54
|
+
import { Icon } from '@genarou/blazir-icons'
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<Icon name="check" />
|
|
58
|
+
<Icon name="home" size={24} color="var(--primary)" />
|
|
59
|
+
<Icon name="settings" preset="muted" />
|
|
60
|
+
<Icon name="trash" variant="danger" />
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
> The CSS animation stylesheet is injected automatically on import. No manual CSS setup required.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## How It Works
|
|
68
|
+
|
|
69
|
+
### Architecture overview
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
<Icon> ← Public wrapper
|
|
73
|
+
│
|
|
74
|
+
├─ preset + variant → getPresetVariantMerge() (frozen, stable reference)
|
|
75
|
+
├─ user props → arePropsStable() check
|
|
76
|
+
│ ├─ all primitives → LRU cache (128 entries) — same config = same reference
|
|
77
|
+
│ └─ objects/actions → direct merge (no cache, but baseProps stays stable)
|
|
78
|
+
│
|
|
79
|
+
├─ lazy=false (default) → iconRegistry[name] (static import, zero latency)
|
|
80
|
+
└─ lazy=true → getLoadedIcon() || loadIcon() (dynamic import + skeleton)
|
|
81
|
+
|
|
82
|
+
<IconBase> ← SVG renderer
|
|
83
|
+
├─ receives merged IconProps
|
|
84
|
+
├─ applies mode (solid / outline / duotone)
|
|
85
|
+
├─ computes hover color, transitions, animations
|
|
86
|
+
├─ binds effects action to the <g> layer
|
|
87
|
+
└─ renders <svg> with full a11y attributes
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Smart Cache (LRU)
|
|
91
|
+
|
|
92
|
+
The cache operates in two layers:
|
|
93
|
+
|
|
94
|
+
1. **Preset/Variant merge** — `getPresetVariantMerge(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.
|
|
95
|
+
|
|
96
|
+
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.
|
|
97
|
+
|
|
98
|
+
Props containing objects (`effects`, `actions`, `attrs`, `parentHoverContext`) bypass the global LRU and are merged directly. The preset/variant base remains stable regardless.
|
|
99
|
+
|
|
100
|
+
This design makes blazir-icons suitable for high-frequency render contexts like data grids, virtualized lists, and real-time dashboards.
|
|
101
|
+
|
|
102
|
+
### Lazy Loading internals
|
|
103
|
+
|
|
104
|
+
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`.
|
|
105
|
+
|
|
106
|
+
When `lazy={true}`:
|
|
107
|
+
1. Svelte checks `getLoadedIcon(name)` — a synchronous in-memory cache of already-loaded modules.
|
|
108
|
+
2. If found, renders immediately (zero visible latency on subsequent navigations).
|
|
109
|
+
3. If not found, sets `isLoading = true` (shows a skeleton placeholder), calls `loadIcon(name)` (dynamic `import()`), and updates the component when the module resolves.
|
|
110
|
+
4. If the `name` prop changes before the load completes, the stale result is discarded — no race conditions.
|
|
111
|
+
|
|
112
|
+
### Actions diff bridge
|
|
113
|
+
|
|
114
|
+
The `actions` prop accepts an array of `[actionFn, params]` tuples. On update, the bridge diffs the new array against the previous one:
|
|
115
|
+
|
|
116
|
+
- If all action **functions** are the same references → only `update(newParams)` is called. Internal state is preserved (e.g. tooltip position, IntersectionObserver).
|
|
117
|
+
- If any function reference changed → `destroy()` + `recreate()` for that action.
|
|
118
|
+
|
|
119
|
+
This is critical for stateful actions like tooltips or lazy-load observers that should not be torn down on every prop change.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Icon Names
|
|
124
|
+
|
|
125
|
+
Every icon has a direct string name and a typed alias via `bzIcons`.
|
|
126
|
+
|
|
127
|
+
```svelte
|
|
128
|
+
<script>
|
|
129
|
+
import { Icon, bzIcons } from '@genarou/blazir-icons'
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<!-- Direct string (plugin can tree-shake this) -->
|
|
133
|
+
<Icon name="check" />
|
|
134
|
+
|
|
135
|
+
<!-- Typed alias — full autocomplete, same result -->
|
|
136
|
+
<Icon name={bzIcons.Check} />
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Available `bzIcons` aliases
|
|
140
|
+
|
|
141
|
+
All 163 icons organized by category. Use the alias for TypeScript autocomplete or the name as a plain string.
|
|
142
|
+
|
|
143
|
+
#### Navigation & Layout
|
|
144
|
+
|
|
145
|
+
| Alias | `name` |
|
|
146
|
+
|---|---|
|
|
147
|
+
| `bzIcons.Home` | `home` |
|
|
148
|
+
| `bzIcons.Dashboard` | `dashboard` |
|
|
149
|
+
| `bzIcons.DashboardOutline` | `dashboardOutline` |
|
|
150
|
+
| `bzIcons.Settings` | `settings` |
|
|
151
|
+
| `bzIcons.Search` | `search` |
|
|
152
|
+
| `bzIcons.Filter` | `filter` |
|
|
153
|
+
| `bzIcons.Menu` | `menu` |
|
|
154
|
+
| `bzIcons.Close` | `close` |
|
|
155
|
+
| `bzIcons.Plus` | `plus` |
|
|
156
|
+
| `bzIcons.Copy` | `copy` |
|
|
157
|
+
| `bzIcons.Rocket` | `rocket` |
|
|
158
|
+
| `bzIcons.Sidebar` | `sidebar` |
|
|
159
|
+
| `bzIcons.More` | `more` |
|
|
160
|
+
|
|
161
|
+
#### Users & Auth
|
|
162
|
+
|
|
163
|
+
| Alias | `name` |
|
|
164
|
+
|---|---|
|
|
165
|
+
| `bzIcons.User` | `user` |
|
|
166
|
+
| `bzIcons.UserTie` | `userTie` |
|
|
167
|
+
| `bzIcons.Team` | `team` |
|
|
168
|
+
| `bzIcons.Group` | `group` |
|
|
169
|
+
| `bzIcons.Supervisor` | `supervisor` |
|
|
170
|
+
| `bzIcons.Enterprise` | `enterprise` |
|
|
171
|
+
| `bzIcons.Lock` | `lock` |
|
|
172
|
+
| `bzIcons.LockOpen` | `lockOpen` |
|
|
173
|
+
| `bzIcons.Key` | `key` |
|
|
174
|
+
| `bzIcons.Logout` | `logout` |
|
|
175
|
+
| `bzIcons.Eye` | `eye` |
|
|
176
|
+
| `bzIcons.EyeOff` | `eyeOff` |
|
|
177
|
+
| `bzIcons.Shield` | `shield` |
|
|
178
|
+
| `bzIcons.Fingerprint` | `fingerprint` |
|
|
179
|
+
| `bzIcons.Contact` | `contact` |
|
|
180
|
+
| `bzIcons.Security` | `security` |
|
|
181
|
+
|
|
182
|
+
#### Communication
|
|
183
|
+
|
|
184
|
+
| Alias | `name` |
|
|
185
|
+
|---|---|
|
|
186
|
+
| `bzIcons.Email` | `email` |
|
|
187
|
+
| `bzIcons.EmailAnimated` | `emailAnimated` |
|
|
188
|
+
| `bzIcons.Phone` | `phone` |
|
|
189
|
+
| `bzIcons.Bell` | `bell` |
|
|
190
|
+
| `bzIcons.Send` | `send` |
|
|
191
|
+
| `bzIcons.Share` | `share` |
|
|
192
|
+
| `bzIcons.World` | `world` |
|
|
193
|
+
| `bzIcons.Chat` | `chat` |
|
|
194
|
+
| `bzIcons.Link` | `link` |
|
|
195
|
+
|
|
196
|
+
#### Business & Finance
|
|
197
|
+
|
|
198
|
+
| Alias | `name` |
|
|
199
|
+
|---|---|
|
|
200
|
+
| `bzIcons.Building` | `building` |
|
|
201
|
+
| `bzIcons.Handshake` | `handshake` |
|
|
202
|
+
| `bzIcons.Money` | `money` |
|
|
203
|
+
| `bzIcons.Wallet` | `wallet` |
|
|
204
|
+
| `bzIcons.Profit` | `profit` |
|
|
205
|
+
| `bzIcons.Safe` | `safe` |
|
|
206
|
+
| `bzIcons.Cost` | `cost` |
|
|
207
|
+
| `bzIcons.Exchange` | `exchange` |
|
|
208
|
+
| `bzIcons.Swap` | `swap` |
|
|
209
|
+
| `bzIcons.Bank` | `bank` |
|
|
210
|
+
| `bzIcons.Pay` | `pay` |
|
|
211
|
+
| `bzIcons.CreditCard` | `creditCard` |
|
|
212
|
+
| `bzIcons.Receipt` | `receipt` |
|
|
213
|
+
| `bzIcons.Buy` | `buy` |
|
|
214
|
+
|
|
215
|
+
#### Charts & Data
|
|
216
|
+
|
|
217
|
+
| Alias | `name` |
|
|
218
|
+
|---|---|
|
|
219
|
+
| `bzIcons.Chart` | `chart` |
|
|
220
|
+
| `bzIcons.ChartDocument` | `chartDocument` |
|
|
221
|
+
| `bzIcons.ChartSquare` | `chartSquare` |
|
|
222
|
+
| `bzIcons.ChartDoughnut` | `chartDoughnut` |
|
|
223
|
+
| `bzIcons.Table` | `table` |
|
|
224
|
+
| `bzIcons.List` | `list` |
|
|
225
|
+
| `bzIcons.ListDots` | `listDots` |
|
|
226
|
+
| `bzIcons.ListGroup` | `listGroup` |
|
|
227
|
+
| `bzIcons.TrendingDown` | `trendingDown` |
|
|
228
|
+
| `bzIcons.Database` | `database` |
|
|
229
|
+
| `bzIcons.Server` | `server` |
|
|
230
|
+
|
|
231
|
+
#### Files & Documents
|
|
232
|
+
|
|
233
|
+
| Alias | `name` |
|
|
234
|
+
|---|---|
|
|
235
|
+
| `bzIcons.File` | `file` |
|
|
236
|
+
| `bzIcons.Pdf` | `pdf` |
|
|
237
|
+
| `bzIcons.Excel` | `excel` |
|
|
238
|
+
| `bzIcons.ExcelAnimated` | `excelAnimated` |
|
|
239
|
+
| `bzIcons.Word` | `word` |
|
|
240
|
+
| `bzIcons.PowerPoint` | `powerPoint` |
|
|
241
|
+
| `bzIcons.Csv` | `csv` |
|
|
242
|
+
| `bzIcons.Xml` | `xml` |
|
|
243
|
+
| `bzIcons.Zip` | `zip` |
|
|
244
|
+
| `bzIcons.Png` | `png` |
|
|
245
|
+
| `bzIcons.Notes` | `notes` |
|
|
246
|
+
| `bzIcons.Book` | `book` |
|
|
247
|
+
| `bzIcons.Image` | `image` |
|
|
248
|
+
| `bzIcons.ImageAnimated` | `imageAnimated` |
|
|
249
|
+
| `bzIcons.Folder` | `folder` |
|
|
250
|
+
| `bzIcons.FolderShared` | `folderShared` |
|
|
251
|
+
| `bzIcons.Attachment` | `attachment` |
|
|
252
|
+
| `bzIcons.Save` | `save` |
|
|
253
|
+
| `bzIcons.Form` | `form` |
|
|
254
|
+
| `bzIcons.Print` | `print` |
|
|
255
|
+
|
|
256
|
+
#### Calendar & Time
|
|
257
|
+
|
|
258
|
+
| Alias | `name` |
|
|
259
|
+
|---|---|
|
|
260
|
+
| `bzIcons.Calendar` | `calendar` |
|
|
261
|
+
| `bzIcons.CalendarPlus` | `calendarPlus` |
|
|
262
|
+
| `bzIcons.CalendarEdit` | `calendarEdit` |
|
|
263
|
+
| `bzIcons.Timer` | `timer` |
|
|
264
|
+
|
|
265
|
+
#### Arrows & Navigation
|
|
266
|
+
|
|
267
|
+
| Alias | `name` |
|
|
268
|
+
|---|---|
|
|
269
|
+
| `bzIcons.ArrowRight` | `arrowRight` |
|
|
270
|
+
| `bzIcons.ArrowUp` | `arrowUp` |
|
|
271
|
+
| `bzIcons.ArrowUpDown` | `arrowUpDown` |
|
|
272
|
+
| `bzIcons.ArrowLeftAnimated` | `arrowLeftAnimated` |
|
|
273
|
+
| `bzIcons.ChevronDown` | `chevronDown` |
|
|
274
|
+
| `bzIcons.ChevronUpDown` | `chevronUpDown` |
|
|
275
|
+
|
|
276
|
+
#### File Actions
|
|
277
|
+
|
|
278
|
+
| Alias | `name` |
|
|
279
|
+
|---|---|
|
|
280
|
+
| `bzIcons.Download` | `download` |
|
|
281
|
+
| `bzIcons.DownloadAnimated` | `downloadAnimated` |
|
|
282
|
+
| `bzIcons.Upload` | `upload` |
|
|
283
|
+
| `bzIcons.UploadAnimated` | `uploadAnimated` |
|
|
284
|
+
| `bzIcons.UploadProgress` | `uploadProgress` |
|
|
285
|
+
| `bzIcons.FileUploadAnimated` | `fileUploadAnimated` |
|
|
286
|
+
| `bzIcons.Refresh` | `refresh` |
|
|
287
|
+
|
|
288
|
+
#### States & Feedback
|
|
289
|
+
|
|
290
|
+
| Alias | `name` |
|
|
291
|
+
|---|---|
|
|
292
|
+
| `bzIcons.Check` | `check` |
|
|
293
|
+
| `bzIcons.CheckOutline` | `checkOutline` |
|
|
294
|
+
| `bzIcons.CheckList` | `checkList` |
|
|
295
|
+
| `bzIcons.CircleCheck` | `circleCheck` |
|
|
296
|
+
| `bzIcons.Error` | `error` |
|
|
297
|
+
| `bzIcons.ErrorOutline` | `errorOutline` |
|
|
298
|
+
| `bzIcons.CircleExclamation` | `circleExclamation` |
|
|
299
|
+
| `bzIcons.CircleExclamationOutline` | `circleExclamationOutline` |
|
|
300
|
+
| `bzIcons.Warning` | `warning` |
|
|
301
|
+
| `bzIcons.CircleInfo` | `circleInfo` |
|
|
302
|
+
| `bzIcons.CircleInfoOutline` | `circleInfoOutline` |
|
|
303
|
+
| `bzIcons.CircleQuestion` | `circleQuestion` |
|
|
304
|
+
| `bzIcons.CircleQuestionOutline` | `circleQuestionOutline` |
|
|
305
|
+
| `bzIcons.Star` | `star` |
|
|
306
|
+
| `bzIcons.Favorites` | `favorites` |
|
|
307
|
+
| `bzIcons.Heart` | `heart` |
|
|
308
|
+
| `bzIcons.Reset` | `reset` |
|
|
309
|
+
| `bzIcons.Height` | `height` |
|
|
310
|
+
| `bzIcons.Alternate` | `alternate` |
|
|
311
|
+
| `bzIcons.Moon` | `moon` |
|
|
312
|
+
| `bzIcons.Sun` | `sun` |
|
|
313
|
+
| `bzIcons.Colors` | `colors` |
|
|
314
|
+
|
|
315
|
+
#### Loading & Progress
|
|
316
|
+
|
|
317
|
+
| Alias | `name` |
|
|
318
|
+
|---|---|
|
|
319
|
+
| `bzIcons.SpinnerDots` | `spinnerDots` |
|
|
320
|
+
| `bzIcons.Spinner` | `spinner` |
|
|
321
|
+
|
|
322
|
+
#### Commerce & Sales
|
|
323
|
+
|
|
324
|
+
| Alias | `name` |
|
|
325
|
+
|---|---|
|
|
326
|
+
| `bzIcons.Product` | `product` |
|
|
327
|
+
| `bzIcons.Bag` | `bag` |
|
|
328
|
+
| `bzIcons.POS` | `pos` |
|
|
329
|
+
| `bzIcons.Category` | `category` |
|
|
330
|
+
| `bzIcons.CategoryAdd` | `categoryAdd` |
|
|
331
|
+
| `bzIcons.CategorySearch` | `categorySearch` |
|
|
332
|
+
| `bzIcons.BoxAdd` | `boxAdd` |
|
|
333
|
+
| `bzIcons.Measure` | `measure` |
|
|
334
|
+
| `bzIcons.Box` | `box` |
|
|
335
|
+
| `bzIcons.Scan` | `scan` |
|
|
336
|
+
| `bzIcons.Cart` | `cart` |
|
|
337
|
+
| `bzIcons.Cards` | `cards` |
|
|
338
|
+
|
|
339
|
+
#### Logistics & Transport
|
|
340
|
+
|
|
341
|
+
| Alias | `name` |
|
|
342
|
+
|---|---|
|
|
343
|
+
| `bzIcons.Truck` | `truck` |
|
|
344
|
+
| `bzIcons.TruckReturn` | `truckReturn` |
|
|
345
|
+
| `bzIcons.Warehouse` | `warehouse` |
|
|
346
|
+
| `bzIcons.Location` | `location` |
|
|
347
|
+
| `bzIcons.LocationAnimated` | `locationAnimated` |
|
|
348
|
+
|
|
349
|
+
#### Tools & Utilities
|
|
350
|
+
|
|
351
|
+
| Alias | `name` |
|
|
352
|
+
|---|---|
|
|
353
|
+
| `bzIcons.AI` | `ai` |
|
|
354
|
+
| `bzIcons.Edit` | `edit` |
|
|
355
|
+
| `bzIcons.EditOutline` | `editOutline` |
|
|
356
|
+
| `bzIcons.Trash` | `trash` |
|
|
357
|
+
| `bzIcons.TrashOutline` | `trashOutline` |
|
|
358
|
+
| `bzIcons.Tags` | `tags` |
|
|
359
|
+
| `bzIcons.Tools` | `tools` |
|
|
360
|
+
| `bzIcons.ObjectGroup` | `objectGroup` |
|
|
361
|
+
| `bzIcons.Project` | `project` |
|
|
362
|
+
|
|
363
|
+
#### Media & Devices
|
|
364
|
+
|
|
365
|
+
| Alias | `name` |
|
|
366
|
+
|---|---|
|
|
367
|
+
| `bzIcons.Camera` | `camera` |
|
|
368
|
+
| `bzIcons.Desktop` | `desktop` |
|
|
369
|
+
| `bzIcons.Wifi` | `wifi` |
|
|
370
|
+
| `bzIcons.Power` | `power` |
|
|
371
|
+
|
|
372
|
+
#### Cloud
|
|
373
|
+
|
|
374
|
+
| Alias | `name` |
|
|
375
|
+
|---|---|
|
|
376
|
+
| `bzIcons.CloudAlert` | `cloudAlert` |
|
|
377
|
+
| `bzIcons.CloudCheck` | `cloudCheck` |
|
|
378
|
+
| `bzIcons.CloudDownload` | `cloudDownload` |
|
|
379
|
+
|
|
380
|
+
#### Other
|
|
381
|
+
|
|
382
|
+
| Alias | `name` |
|
|
383
|
+
|---|---|
|
|
384
|
+
| `bzIcons.Blaze` | `blaze` |
|
|
385
|
+
| `bzIcons.Earth` | `earth` |
|
|
386
|
+
| `bzIcons.Globe` | `globe` |
|
|
387
|
+
| `bzIcons.LightHub` | `lightHub` |
|
|
388
|
+
| `bzIcons.Sync` | `sync` |
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## Props Reference
|
|
393
|
+
|
|
394
|
+
All props are optional. Every prop can be passed to `<Icon>` or `<IconBase>`.
|
|
395
|
+
|
|
396
|
+
### Visual
|
|
397
|
+
|
|
398
|
+
| Prop | Type | Default | Description |
|
|
399
|
+
|---|---|---|---|
|
|
400
|
+
| `name` | `IconName` | — | Icon identifier |
|
|
401
|
+
| `size` | `number \| string` | `24` | Width and height. Accepts `px`, `rem`, `em`, token (`sm`, `md`, `lg`, etc.) or a plain number |
|
|
402
|
+
| `color` | `string` | `currentColor` | Fill or stroke color |
|
|
403
|
+
| `stroke` | `string` | — | Explicit stroke color (overrides `color` for stroke) |
|
|
404
|
+
| `strokeWidth` | `number \| string` | — | SVG stroke width |
|
|
405
|
+
| `strokeLinecap` | `"round" \| "butt" \| "square"` | — | SVG stroke-linecap attribute |
|
|
406
|
+
| `strokeLinejoin` | `"round" \| "miter" \| "bevel"` | — | SVG stroke-linejoin attribute |
|
|
407
|
+
| `fill` | `string` | — | Explicit fill color |
|
|
408
|
+
| `mode` | `"solid" \| "outline" \| "duotone"` | `"solid"` | Rendering mode |
|
|
409
|
+
| `viewBox` | `string` | `"0 0 24 24"` | SVG viewBox attribute |
|
|
410
|
+
| `preserveAspectRatio` | `string` | — | SVG preserveAspectRatio attribute |
|
|
411
|
+
| `class` | `string` | — | CSS class on the wrapper element |
|
|
412
|
+
| `className` | `string` | — | Alias for `class` |
|
|
413
|
+
| `style` | `string` | — | Inline style on the wrapper element |
|
|
414
|
+
| `attrs` | `Record<string, any>` | — | Arbitrary extra attributes forwarded to the `<svg>` element (excluding `width`/`height`) |
|
|
415
|
+
|
|
416
|
+
### Size Tokens
|
|
417
|
+
|
|
418
|
+
| Token | Value |
|
|
419
|
+
|---|---|
|
|
420
|
+
| `xs` | 12px |
|
|
421
|
+
| `sm` | 16px |
|
|
422
|
+
| `md` | 20px |
|
|
423
|
+
| `lg` | 24px |
|
|
424
|
+
| `xl` | 32px |
|
|
425
|
+
| `2xl` | 40px |
|
|
426
|
+
| `3xl` | 48px |
|
|
427
|
+
|
|
428
|
+
```svelte
|
|
429
|
+
<Icon name="check" size="sm" />
|
|
430
|
+
<Icon name="check" size={32} />
|
|
431
|
+
<Icon name="check" size="1.5rem" />
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Transform
|
|
435
|
+
|
|
436
|
+
| Prop | Type | Default | Description |
|
|
437
|
+
|---|---|---|---|
|
|
438
|
+
| `rotate` | `number \| string` | — | Rotation in degrees or CSS string |
|
|
439
|
+
| `flipH` | `boolean` | `false` | Flip horizontally |
|
|
440
|
+
| `flipV` | `boolean` | `false` | Flip vertically |
|
|
441
|
+
| `nonScalingStroke` | `boolean` | `false` | Keep stroke width fixed regardless of transform (`vector-effect="non-scaling-stroke"`) |
|
|
442
|
+
|
|
443
|
+
```svelte
|
|
444
|
+
<Icon name="arrow" rotate={45} />
|
|
445
|
+
<Icon name="arrow" flipH />
|
|
446
|
+
<Icon name="arrow" rotate={90} flipV />
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Animations
|
|
450
|
+
|
|
451
|
+
| Prop | Type | Default | Description |
|
|
452
|
+
|---|---|---|---|
|
|
453
|
+
| `spin` | `boolean \| number \| string` | `false` | Continuous rotation. `true` = 1s linear, number = duration in ms |
|
|
454
|
+
| `pulse` | `boolean` | `false` | Opacity + scale pulse |
|
|
455
|
+
| `bounce` | `boolean` | `false` | Vertical bounce |
|
|
456
|
+
| `wiggle` | `boolean` | `false` | Left-right rotation wiggle |
|
|
457
|
+
| `heartbeat` | `boolean` | `false` | Double-pulse heartbeat effect |
|
|
458
|
+
| `elastic` | `boolean` | `false` | Elastic scale pop |
|
|
459
|
+
| `animationDuration` | `number \| string` | — | Override animation duration (`400`, `"400ms"`, `"0.4s"`) |
|
|
460
|
+
| `animationDelay` | `number \| string` | — | Animation start delay |
|
|
461
|
+
| `animationEasing` | `string` | — | CSS easing function |
|
|
462
|
+
|
|
463
|
+
```svelte
|
|
464
|
+
<Icon name="loadingDots" spin />
|
|
465
|
+
<Icon name="loadingDots" spin={800} />
|
|
466
|
+
<Icon name="bell" bounce animationDuration={600} />
|
|
467
|
+
<Icon name="heart" heartbeat animationDelay="200ms" />
|
|
468
|
+
<Icon name="star" pulse animationEasing="ease-in-out" />
|
|
469
|
+
|
|
470
|
+
<!-- Combine multiple animations -->
|
|
471
|
+
<Icon name="loadingRegular" spin pulse />
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### Entry Transitions
|
|
475
|
+
|
|
476
|
+
| Prop | Type | Description |
|
|
477
|
+
|---|---|---|
|
|
478
|
+
| `scaleIn` | `boolean` | Animate in with a scale effect |
|
|
479
|
+
| `fadeIn` | `boolean` | Animate in with a fade effect |
|
|
480
|
+
| `slideIn` | `boolean` | Animate in with a slide effect |
|
|
481
|
+
| `slideDirection` | `"up" \| "down" \| "left" \| "right"` | Direction for `slideIn` |
|
|
482
|
+
| `morphTo` | `"play" \| "pause" \| "menu" \| "close" \| "arrow" \| "check"` | Morph the icon shape to a target state |
|
|
483
|
+
| `chevronState` | `"open" \| "closed" \| "up" \| "down" \| "left" \| "right"` | Rotate a chevron icon to indicate state |
|
|
484
|
+
| `chevronOpen` | `boolean` | Shorthand: `true` = `chevronState="open"` |
|
|
485
|
+
|
|
486
|
+
```svelte
|
|
487
|
+
<!-- Animated menu toggle -->
|
|
488
|
+
<Icon name="hamburguer" morphTo={isOpen ? 'close' : 'menu'} />
|
|
489
|
+
|
|
490
|
+
<!-- Animated accordion chevron -->
|
|
491
|
+
<Icon name="chevronDown" chevronOpen={isExpanded} />
|
|
492
|
+
|
|
493
|
+
<!-- Entry animations -->
|
|
494
|
+
<Icon name="check" scaleIn />
|
|
495
|
+
<Icon name="warning" fadeIn />
|
|
496
|
+
<Icon name="bell" slideIn slideDirection="down" />
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### Interaction
|
|
500
|
+
|
|
501
|
+
| Prop | Type | Default | Description |
|
|
502
|
+
|---|---|---|---|
|
|
503
|
+
| `hoverColor` | `string` | — | Color applied on hover |
|
|
504
|
+
| `activeColor` | `string` | — | Color applied on press/active. Priority: `activeColor` > `hoverColor` > `color` |
|
|
505
|
+
| `disabled` | `boolean` | `false` | Reduces opacity to 0.4 and disables all pointer events and hover effects |
|
|
506
|
+
| `loading` | `boolean` | `false` | Replaces the icon with a spinning circle until `false`. Reuses internal spin keyframe — zero extra weight |
|
|
507
|
+
| `tooltip` | `string` | — | Native browser tooltip. Shorthand for `effects={{ tooltip: "..." }}` |
|
|
508
|
+
| `hoverSpeed` | `"instant" \| "fast" \| "normal" \| "slow" \| "sluggish"` | `"normal"` | Semantic preset for hover transition speed |
|
|
509
|
+
| `transitionMs` | `number \| string` | `250` | Exact hover transition duration. Overrides `hoverSpeed` |
|
|
510
|
+
| `transitionEasing` | `string` | `"ease"` | CSS easing for hover transition |
|
|
511
|
+
| `parentHoverContext` | `{ hovered: boolean }` | — | Trigger hover state from a parent element |
|
|
512
|
+
|
|
513
|
+
#### `hoverSpeed` presets
|
|
514
|
+
|
|
515
|
+
| Value | Duration |
|
|
516
|
+
|---|---|
|
|
517
|
+
| `"instant"` | 0ms |
|
|
518
|
+
| `"fast"` | 120ms |
|
|
519
|
+
| `"normal"` | 250ms ← default |
|
|
520
|
+
| `"slow"` | 400ms |
|
|
521
|
+
| `"sluggish"` | 600ms |
|
|
522
|
+
|
|
523
|
+
```svelte
|
|
524
|
+
<!-- Hover color with speed preset -->
|
|
525
|
+
<Icon name="edit" hoverColor="var(--primary)" hoverSpeed="fast" />
|
|
526
|
+
|
|
527
|
+
<!-- Active/press color -->
|
|
528
|
+
<Icon name="heart" hoverColor="#f97316" activeColor="#dc2626" />
|
|
529
|
+
|
|
530
|
+
<!-- Disabled state -->
|
|
531
|
+
<Icon name="send" disabled />
|
|
532
|
+
<Icon name="save" disabled={!isFormValid} />
|
|
533
|
+
|
|
534
|
+
<!-- Loading state — auto spinner, no wrapper needed -->
|
|
535
|
+
<Icon name="save" loading={isSaving} />
|
|
536
|
+
|
|
537
|
+
<!-- Tooltip -->
|
|
538
|
+
<Icon name="info" tooltip="More information" />
|
|
539
|
+
|
|
540
|
+
<!-- Custom easing -->
|
|
541
|
+
<Icon name="bell" hoverColor="var(--primary)" transitionMs={350} transitionEasing="ease-in-out" />
|
|
542
|
+
|
|
543
|
+
<!-- Trigger icon hover when parent row is hovered -->
|
|
544
|
+
<script>
|
|
545
|
+
let hovered = $state(false)
|
|
546
|
+
const ctx = $derived({ hovered })
|
|
547
|
+
</script>
|
|
548
|
+
<tr onmouseenter={() => hovered = true} onmouseleave={() => hovered = false}>
|
|
549
|
+
<td><Icon name="edit" parentHoverContext={ctx} hoverColor="var(--primary)" /></td>
|
|
550
|
+
</tr>
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Compact Mode
|
|
554
|
+
|
|
555
|
+
Reduces visual weight of solid icons at small sizes by adjusting opacity.
|
|
556
|
+
|
|
557
|
+
| Prop | Type | Default | Description |
|
|
558
|
+
|---|---|---|---|
|
|
559
|
+
| `compact` | `"off" \| "auto" \| "outline" \| "duotone"` | `"off"` | Compact rendering mode |
|
|
560
|
+
| `compactSizeThreshold` | `number` | `20` | Size in px below which compact activates (when `"auto"`) |
|
|
561
|
+
| `compactFillOpacity` | `number` | `0.15` | Fill opacity in compact mode |
|
|
562
|
+
| `compactStrokeWidth` | `number \| string` | — | Stroke width in compact mode |
|
|
563
|
+
|
|
564
|
+
```svelte
|
|
565
|
+
<!-- Auto: switches to outline style below 20px -->
|
|
566
|
+
<Icon name="user" compact="auto" size={16} />
|
|
567
|
+
|
|
568
|
+
<!-- Always compact duotone -->
|
|
569
|
+
<Icon name="folder" compact="duotone" compactFillOpacity={0.2} />
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
### Accessibility
|
|
573
|
+
|
|
574
|
+
| Prop | Type | Default | Description |
|
|
575
|
+
|---|---|---|---|
|
|
576
|
+
| `ariaLabel` | `string` | Icon name | `aria-label` on the SVG |
|
|
577
|
+
| `title` | `string` | — | SVG `<title>` element (tooltip on hover in browsers) |
|
|
578
|
+
| `titleId` | `string` | — | `id` for the `<title>` element (for `aria-labelledby`) |
|
|
579
|
+
| `decorative` | `boolean` | `false` | Sets `aria-hidden="true"` — use when icon is purely decorative |
|
|
580
|
+
| `testId` | `string` | — | `data-testid` attribute |
|
|
581
|
+
|
|
582
|
+
```svelte
|
|
583
|
+
<!-- Decorative icon next to a labeled button -->
|
|
584
|
+
<button>
|
|
585
|
+
<Icon name="download" decorative />
|
|
586
|
+
Download
|
|
587
|
+
</button>
|
|
588
|
+
|
|
589
|
+
<!-- Standalone meaningful icon -->
|
|
590
|
+
<Icon name="check" ariaLabel="Task completed" />
|
|
591
|
+
|
|
592
|
+
<!-- With visible tooltip -->
|
|
593
|
+
<Icon name="info" title="More information" ariaLabel="More information" />
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### Lazy Loading Prop
|
|
597
|
+
|
|
598
|
+
| Prop | Type | Default | Description |
|
|
599
|
+
|---|---|---|---|
|
|
600
|
+
| `lazy` | `boolean` | `false` | Load the icon as a separate dynamic import, enabling per-icon code splitting. Shows a skeleton placeholder while loading. |
|
|
601
|
+
|
|
602
|
+
```svelte
|
|
603
|
+
<!-- Eager (default) — bundled with registry -->
|
|
604
|
+
<Icon name="check" />
|
|
605
|
+
|
|
606
|
+
<!-- Lazy — separate chunk, skeleton while loading -->
|
|
607
|
+
<Icon name="check" lazy />
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
---
|
|
611
|
+
|
|
612
|
+
## Presets
|
|
613
|
+
|
|
614
|
+
Presets apply a predefined set of props in one shot. Define colors, sizes, and behaviors using your CSS design tokens.
|
|
615
|
+
|
|
616
|
+
```svelte
|
|
617
|
+
<Icon name="check" preset="success" />
|
|
618
|
+
<Icon name="home" preset="nav" />
|
|
619
|
+
<Icon name="plus" preset="button" />
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
| Preset | Properties |
|
|
623
|
+
|---|---|
|
|
624
|
+
| `primary` | `color: var(--primary)`, `hoverColor: var(--primary-hover)` |
|
|
625
|
+
| `secondary` | `color: var(--secondary)`, `hoverColor: var(--secondary-foreground)` |
|
|
626
|
+
| `accent` | `color: var(--accent-color)`, `hoverColor: var(--accent-hover)` |
|
|
627
|
+
| `success` | `color: var(--success-color)`, `hoverColor: var(--success-hover)` |
|
|
628
|
+
| `warning` | `color: var(--warning-color)`, `hoverColor: var(--warning-hover)` |
|
|
629
|
+
| `danger` | `color: var(--danger-color)`, `hoverColor: var(--danger-hover)` |
|
|
630
|
+
| `muted` | `color: var(--icon-fg, var(--ui-muted-fg))`, hover → foreground |
|
|
631
|
+
| `nav` | `size: 24`, nav colors, subtle scale on hover |
|
|
632
|
+
| `sidebar` | `size: 18`, sidebar colors, scale on hover |
|
|
633
|
+
| `button` | `size: 20`, `currentColor`, cursor pointer, scale on hover |
|
|
634
|
+
| `badge` | `size: 16`, compact auto |
|
|
635
|
+
| `hero` | `size: 48`, primary color, bounce on hover |
|
|
636
|
+
| `loading` | `spin: true`, `size: 24`, primary color |
|
|
637
|
+
|
|
638
|
+
Props passed directly always override preset values.
|
|
639
|
+
|
|
640
|
+
```svelte
|
|
641
|
+
<!-- preset sets size=24, but size={32} wins -->
|
|
642
|
+
<Icon name="check" preset="nav" size={32} />
|
|
643
|
+
|
|
644
|
+
<!-- preset + variant combination -->
|
|
645
|
+
<Icon name="trash" preset="button" variant="danger" />
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|
|
650
|
+
## Variants
|
|
651
|
+
|
|
652
|
+
Variants apply a color scheme without touching size or behavior. Combine with presets for full control.
|
|
653
|
+
|
|
654
|
+
```svelte
|
|
655
|
+
<Icon name="check" preset="button" variant="success" />
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
| Variant | Color token |
|
|
659
|
+
|---|---|
|
|
660
|
+
| `primary` | `var(--primary)` |
|
|
661
|
+
| `secondary` | `var(--secondary)` |
|
|
662
|
+
| `accent` | `var(--accent-color)` |
|
|
663
|
+
| `success` | `var(--success-color)` |
|
|
664
|
+
| `warning` | `var(--warning-color)` |
|
|
665
|
+
| `danger` | `var(--danger-color)` |
|
|
666
|
+
| `muted` | `var(--icon-fg, var(--ui-muted-fg))` |
|
|
667
|
+
| `ghost` | `var(--ui-muted-fg)` |
|
|
668
|
+
|
|
669
|
+
---
|
|
670
|
+
|
|
671
|
+
## Lazy Loading
|
|
672
|
+
|
|
673
|
+
By default icons load eagerly (zero latency, no skeletons). Add `lazy` to defer loading and enable per-icon code splitting.
|
|
674
|
+
|
|
675
|
+
```svelte
|
|
676
|
+
<!-- Eager (default) — same bundle chunk as always -->
|
|
677
|
+
<Icon name="check" />
|
|
678
|
+
|
|
679
|
+
<!-- Lazy — loaded on first render, skeleton shown while loading -->
|
|
680
|
+
<Icon name="check" lazy />
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
### Manual preload
|
|
684
|
+
|
|
685
|
+
Preload a set of icons before they are needed (e.g. on route anticipation):
|
|
686
|
+
|
|
687
|
+
```ts
|
|
688
|
+
import { preloadIcons } from '@genarou/blazir-icons'
|
|
689
|
+
|
|
690
|
+
// Runs in background via requestIdleCallback
|
|
691
|
+
preloadIcons(['check', 'home', 'settings', 'user'])
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
### Programmatic load
|
|
695
|
+
|
|
696
|
+
```ts
|
|
697
|
+
import { loadIcon, getLoadedIcon } from '@genarou/blazir-icons'
|
|
698
|
+
|
|
699
|
+
// Async load + cache
|
|
700
|
+
const Check = await loadIcon('check')
|
|
701
|
+
|
|
702
|
+
// Synchronous lookup (returns null if not yet loaded)
|
|
703
|
+
const Cached = getLoadedIcon('check')
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
## Effects System
|
|
709
|
+
|
|
710
|
+
Declarative interactive effects applied via the `effects` prop. All effects respect `prefers-reduced-motion`.
|
|
711
|
+
|
|
712
|
+
```svelte
|
|
713
|
+
<Icon
|
|
714
|
+
name="settings"
|
|
715
|
+
effects={{ spinOnHover: true, cursor: 'pointer' }}
|
|
716
|
+
/>
|
|
717
|
+
|
|
718
|
+
<Icon
|
|
719
|
+
name="trash"
|
|
720
|
+
effects={{ wiggleOnHover: true, elasticOnClick: true }}
|
|
721
|
+
/>
|
|
722
|
+
|
|
723
|
+
<Icon
|
|
724
|
+
name="heart"
|
|
725
|
+
effects={{ heartbeatOnHover: true, hoverScale: 1.15 }}
|
|
726
|
+
/>
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
### `IconEffectOptions`
|
|
730
|
+
|
|
731
|
+
| Option | Type | Description |
|
|
732
|
+
|---|---|---|
|
|
733
|
+
| `spinOnHover` | `boolean` | Spin on mouse enter |
|
|
734
|
+
| `bounceOnHover` | `boolean` | Bounce on mouse enter |
|
|
735
|
+
| `wiggleOnHover` | `boolean` | Wiggle on mouse enter |
|
|
736
|
+
| `slideOnHover` | `"up" \| "down" \| "left" \| "right"` | Slide translate on hover |
|
|
737
|
+
| `morphOnHover` | `"play" \| "pause" \| "menu" \| "close" \| "arrow" \| "check"` | Morph shape on hover |
|
|
738
|
+
| `elasticOnClick` | `boolean` | Elastic scale pop on click |
|
|
739
|
+
| `heartbeatOnActive` | `boolean` | Heartbeat on mousedown |
|
|
740
|
+
| `heartbeatOnHover` | `boolean` | Heartbeat on hover |
|
|
741
|
+
| `pulse` | `boolean` | Continuous pulse |
|
|
742
|
+
| `hoverScale` | `number` | Scale factor on hover (`1.1` = 110%) |
|
|
743
|
+
| `pressScale` | `number` | Scale factor on press |
|
|
744
|
+
| `rotateOnHover` | `number` | Degrees to rotate on hover |
|
|
745
|
+
| `transitionMs` | `number` | Transition duration in ms |
|
|
746
|
+
| `easing` | `string` | CSS easing function |
|
|
747
|
+
| `cursor` | `string` | CSS cursor on hover |
|
|
748
|
+
| `tooltip` | `string` | Native title tooltip |
|
|
749
|
+
| `focusRing` | `boolean` | Show visible focus ring |
|
|
750
|
+
| `kbFocusAttr` | `string` | Data attribute set on keyboard focus |
|
|
751
|
+
|
|
752
|
+
### Using `iconEffects` as a Svelte action
|
|
753
|
+
|
|
754
|
+
For advanced cases where you need to apply effects to a custom element:
|
|
755
|
+
|
|
756
|
+
```svelte
|
|
757
|
+
<script>
|
|
758
|
+
import { iconEffects } from '@genarou/blazir-icons'
|
|
759
|
+
</script>
|
|
760
|
+
|
|
761
|
+
<button use:iconEffects={{ spinOnHover: true, hoverScale: 1.1 }}>
|
|
762
|
+
Click me
|
|
763
|
+
</button>
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
---
|
|
767
|
+
|
|
768
|
+
## Actions System
|
|
769
|
+
|
|
770
|
+
Pass Svelte actions to the icon wrapper via the `actions` prop. Actions are diffed on update — state is preserved when params change.
|
|
771
|
+
|
|
772
|
+
```svelte
|
|
773
|
+
<script>
|
|
774
|
+
import { Icon } from '@genarou/blazir-icons'
|
|
775
|
+
import { tooltip } from '$lib/actions/tooltip'
|
|
776
|
+
import { lazyLoad } from '$lib/actions/lazy'
|
|
777
|
+
|
|
778
|
+
let opts = $state({ text: 'Save file' })
|
|
779
|
+
</script>
|
|
780
|
+
|
|
781
|
+
<Icon
|
|
782
|
+
name="save"
|
|
783
|
+
actions={[[tooltip, opts], [lazyLoad]]}
|
|
784
|
+
/>
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
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.
|
|
788
|
+
|
|
789
|
+
---
|
|
790
|
+
|
|
791
|
+
## IconBadge
|
|
792
|
+
|
|
793
|
+
`IconBadge` wraps any icon with an absolute-positioned notification badge. Zero weight unless imported.
|
|
794
|
+
|
|
795
|
+
```svelte
|
|
796
|
+
<script>
|
|
797
|
+
import { IconBadge } from '@genarou/blazir-icons'
|
|
798
|
+
</script>
|
|
799
|
+
|
|
800
|
+
<!-- Dot (boolean) -->
|
|
801
|
+
<IconBadge name="bell" badge />
|
|
802
|
+
|
|
803
|
+
<!-- Count -->
|
|
804
|
+
<IconBadge name="bell" badge={5} />
|
|
805
|
+
|
|
806
|
+
<!-- Text -->
|
|
807
|
+
<IconBadge name="chat" badge="!" />
|
|
808
|
+
|
|
809
|
+
<!-- Custom color and size -->
|
|
810
|
+
<IconBadge name="bell" badge={12} badgeColor="#f59e0b" badgeSize={18} />
|
|
811
|
+
|
|
812
|
+
<!-- Position (default: top-right) -->
|
|
813
|
+
<IconBadge name="bell" badge={3} badgePosition="top-left" />
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
### `IconBadge` props
|
|
817
|
+
|
|
818
|
+
Accepts all `Icon` props plus:
|
|
819
|
+
|
|
820
|
+
| Prop | Type | Default | Description |
|
|
821
|
+
|---|---|---|---|
|
|
822
|
+
| `badge` | `boolean \| number \| string` | — | `true` = dot · number/string = label |
|
|
823
|
+
| `badgeColor` | `string` | `#ef4444` | Badge background color |
|
|
824
|
+
| `badgeSize` | `number` | `8` (dot) / `16` (label) | Badge diameter in px |
|
|
825
|
+
| `badgePosition` | `"top-right" \| "top-left" \| "bottom-right" \| "bottom-left"` | `"top-right"` | Corner placement |
|
|
826
|
+
|
|
827
|
+
> `badge={false}` or omitting `badge` renders the icon directly without any wrapper element — no DOM overhead.
|
|
828
|
+
|
|
829
|
+
---
|
|
830
|
+
|
|
831
|
+
## CustomIcon
|
|
832
|
+
|
|
833
|
+
Render any custom SVG string using the same `IconBase` engine — all effects, transitions, hover colors, animations and a11y props work out of the box.
|
|
834
|
+
|
|
835
|
+
```svelte
|
|
836
|
+
<script>
|
|
837
|
+
import { CustomIcon } from '@genarou/blazir-icons'
|
|
838
|
+
|
|
839
|
+
const logoSvg = `<path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/>`
|
|
840
|
+
</script>
|
|
841
|
+
|
|
842
|
+
<!-- Same API as Icon — all props supported -->
|
|
843
|
+
<CustomIcon svgContent={logoSvg} size={32} color="var(--primary)" />
|
|
844
|
+
|
|
845
|
+
<!-- With hover and effects -->
|
|
846
|
+
<CustomIcon
|
|
847
|
+
svgContent={logoSvg}
|
|
848
|
+
hoverColor="#6366f1"
|
|
849
|
+
hoverSpeed="fast"
|
|
850
|
+
effects={{ hoverScale: 1.1 }}
|
|
851
|
+
/>
|
|
852
|
+
|
|
853
|
+
<!-- With animations -->
|
|
854
|
+
<CustomIcon svgContent={logoSvg} spin pulse />
|
|
855
|
+
|
|
856
|
+
<!-- Custom viewBox for non-24x24 SVGs -->
|
|
857
|
+
<CustomIcon svgContent={logoSvg} viewBox="0 0 48 48" size={48} />
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
### `CustomIcon` props
|
|
861
|
+
|
|
862
|
+
| Prop | Type | Default | Description |
|
|
863
|
+
|---|---|---|---|
|
|
864
|
+
| `svgContent` | `string` | **required** | Raw SVG inner markup (paths, circles, etc. — not the `<svg>` tag itself) |
|
|
865
|
+
| `viewBox` | `string` | `"0 0 24 24"` | ViewBox for the SVG container |
|
|
866
|
+
| + all `IconProps` | | | Every prop from the standard `Icon` is supported |
|
|
867
|
+
|
|
868
|
+
> 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.
|
|
869
|
+
|
|
870
|
+
---
|
|
871
|
+
|
|
872
|
+
## Vite Plugin (Tree Shaking)
|
|
873
|
+
|
|
874
|
+
Without the plugin, all 152 icons are included in your bundle. With the plugin, only the icons you statically reference are bundled.
|
|
875
|
+
|
|
876
|
+
```ts
|
|
877
|
+
// vite.config.ts
|
|
878
|
+
import { blazirIconsPlugin } from '@genarou/blazir-icons/plugin'
|
|
879
|
+
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
|
880
|
+
|
|
881
|
+
export default {
|
|
882
|
+
plugins: [
|
|
883
|
+
blazirIconsPlugin(),
|
|
884
|
+
svelte(),
|
|
885
|
+
]
|
|
886
|
+
}
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
The plugin scans your source files at build time, detects static `name="..."` values, and generates a minimal registry.
|
|
890
|
+
|
|
891
|
+
```svelte
|
|
892
|
+
<!-- Detected statically → only Check.svelte in bundle -->
|
|
893
|
+
<Icon name="check" />
|
|
894
|
+
|
|
895
|
+
<!-- Also detected statically -->
|
|
896
|
+
<Icon name={"home"} />
|
|
897
|
+
|
|
898
|
+
<!-- Dynamic → cannot detect → falls back to full registry (safe) -->
|
|
899
|
+
<Icon name={bzIcons.User} />
|
|
900
|
+
<Icon name={someVariable} />
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
### Plugin Options
|
|
904
|
+
|
|
905
|
+
```ts
|
|
906
|
+
blazirIconsPlugin({
|
|
907
|
+
// Root directory to scan. Default: Vite's config.root
|
|
908
|
+
root: './src',
|
|
909
|
+
|
|
910
|
+
// File extensions to include in scan
|
|
911
|
+
extensions: ['.svelte', '.ts', '.tsx', '.js', '.jsx'],
|
|
912
|
+
})
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
### Bundle size comparison
|
|
916
|
+
|
|
917
|
+
| Scenario | Bundle (gzip) |
|
|
918
|
+
|---|---|
|
|
919
|
+
| No plugin — all 163 icons | ~11 KB |
|
|
920
|
+
| With plugin — 10 static icons | ~1–2 KB |
|
|
921
|
+
| With plugin — dynamic names detected | ~11 KB (safe fallback) |
|
|
922
|
+
|
|
923
|
+
---
|
|
924
|
+
|
|
925
|
+
## Direct Icon Imports
|
|
926
|
+
|
|
927
|
+
Import a single icon component directly for maximum tree shaking without the plugin:
|
|
928
|
+
|
|
929
|
+
```ts
|
|
930
|
+
import Check from '@genarou/blazir-icons/icons/Check'
|
|
931
|
+
import Home from '@genarou/blazir-icons/icons/Home'
|
|
932
|
+
import Settings from '@genarou/blazir-icons/icons/Settings'
|
|
933
|
+
```
|
|
934
|
+
|
|
935
|
+
Use them as regular Svelte components. All `IconProps` are supported, but presets and variants are not applied automatically.
|
|
936
|
+
|
|
937
|
+
```svelte
|
|
938
|
+
<Check size={20} color="var(--success-color)" />
|
|
939
|
+
<Home size={24} hoverColor="var(--primary)" />
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
---
|
|
943
|
+
|
|
944
|
+
## TypeScript
|
|
945
|
+
|
|
946
|
+
Full type coverage on all props and icon names.
|
|
947
|
+
|
|
948
|
+
```ts
|
|
949
|
+
import type { IconProps, IconName, IconMode } from '@genarou/blazir-icons'
|
|
950
|
+
import type { IconEffectOptions } from '@genarou/blazir-icons'
|
|
951
|
+
import type { BzIconKey } from '@genarou/blazir-icons'
|
|
952
|
+
|
|
953
|
+
// Typed icon name
|
|
954
|
+
const icon: IconName = 'check'
|
|
955
|
+
|
|
956
|
+
// Typed effect options
|
|
957
|
+
const effects: IconEffectOptions = {
|
|
958
|
+
spinOnHover: true,
|
|
959
|
+
hoverScale: 1.1,
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
// Typed bzIcons alias
|
|
963
|
+
const key: BzIconKey = 'Check'
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
### Extending the registry
|
|
967
|
+
|
|
968
|
+
```ts
|
|
969
|
+
import { iconRegistry } from '@genarou/blazir-icons'
|
|
970
|
+
|
|
971
|
+
// Autocomplete on all registry keys
|
|
972
|
+
type MyIconName = keyof typeof iconRegistry
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
---
|
|
976
|
+
|
|
977
|
+
## CSS Custom Properties
|
|
978
|
+
|
|
979
|
+
Customize animations globally via CSS variables.
|
|
980
|
+
|
|
981
|
+
| Variable | Default | Description |
|
|
982
|
+
|---|---|---|
|
|
983
|
+
| `--bz-icon-bounce-amt` | `18%` | Bounce height |
|
|
984
|
+
| `--bz-icon-pulse-scale` | `1.04` | Pulse scale factor |
|
|
985
|
+
| `--bz-icon-ring` | primary | Focus ring color |
|
|
986
|
+
| `--bz-icon-wiggle-angle` | `3deg` | Wiggle rotation amount |
|
|
987
|
+
| `--bz-icon-slide-distance` | `8px` | Slide effect distance |
|
|
988
|
+
| `--bz-icon-size` | set by component | Icon size (set automatically) |
|
|
989
|
+
|
|
990
|
+
```css
|
|
991
|
+
/* globals.css */
|
|
992
|
+
:root {
|
|
993
|
+
--bz-icon-bounce-amt: 24%;
|
|
994
|
+
--bz-icon-wiggle-angle: 5deg;
|
|
995
|
+
}
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
---
|
|
999
|
+
|
|
1000
|
+
## Accessibility Guide
|
|
1001
|
+
|
|
1002
|
+
```svelte
|
|
1003
|
+
<!-- Decorative icon — hidden from screen readers -->
|
|
1004
|
+
<button>
|
|
1005
|
+
<Icon name="trash" decorative />
|
|
1006
|
+
Delete item
|
|
1007
|
+
</button>
|
|
1008
|
+
|
|
1009
|
+
<!-- Meaningful standalone icon -->
|
|
1010
|
+
<Icon name="warning" ariaLabel="Warning: unsaved changes" />
|
|
1011
|
+
|
|
1012
|
+
<!-- With visible tooltip -->
|
|
1013
|
+
<Icon name="info" title="More information" ariaLabel="More information" />
|
|
1014
|
+
|
|
1015
|
+
<!-- In a labeled group -->
|
|
1016
|
+
<div aria-label="Status">
|
|
1017
|
+
<Icon name="circleCheck" decorative />
|
|
1018
|
+
<span>All systems operational</span>
|
|
1019
|
+
</div>
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
---
|
|
1023
|
+
|
|
1024
|
+
## Real-World Examples
|
|
1025
|
+
|
|
1026
|
+
### Sidebar navigation item
|
|
1027
|
+
|
|
1028
|
+
```svelte
|
|
1029
|
+
<script>
|
|
1030
|
+
import { Icon } from '@genarou/blazir-icons'
|
|
1031
|
+
export let active = false
|
|
1032
|
+
export let label = ''
|
|
1033
|
+
export let icon = 'home'
|
|
1034
|
+
</script>
|
|
1035
|
+
|
|
1036
|
+
<a class="nav-item" class:active>
|
|
1037
|
+
<Icon
|
|
1038
|
+
name={icon}
|
|
1039
|
+
preset="sidebar"
|
|
1040
|
+
color={active ? 'var(--primary)' : undefined}
|
|
1041
|
+
effects={{ hoverScale: 1.08 }}
|
|
1042
|
+
decorative
|
|
1043
|
+
/>
|
|
1044
|
+
<span>{label}</span>
|
|
1045
|
+
</a>
|
|
1046
|
+
```
|
|
1047
|
+
|
|
1048
|
+
### Loading button
|
|
1049
|
+
|
|
1050
|
+
```svelte
|
|
1051
|
+
<script>
|
|
1052
|
+
import { Icon } from '@genarou/blazir-icons'
|
|
1053
|
+
let saving = $state(false)
|
|
1054
|
+
|
|
1055
|
+
async function submit() {
|
|
1056
|
+
saving = true
|
|
1057
|
+
await doWork()
|
|
1058
|
+
saving = false
|
|
1059
|
+
}
|
|
1060
|
+
</script>
|
|
1061
|
+
|
|
1062
|
+
<!-- The icon swaps to a spinner automatically while saving -->
|
|
1063
|
+
<button onclick={submit} disabled={saving}>
|
|
1064
|
+
<Icon name="save" loading={saving} decorative />
|
|
1065
|
+
{saving ? 'Saving...' : 'Save'}
|
|
1066
|
+
</button>
|
|
1067
|
+
```
|
|
1068
|
+
|
|
1069
|
+
### Animated accordion chevron
|
|
1070
|
+
|
|
1071
|
+
```svelte
|
|
1072
|
+
<script>
|
|
1073
|
+
import { Icon } from '@genarou/blazir-icons'
|
|
1074
|
+
let open = $state(false)
|
|
1075
|
+
</script>
|
|
1076
|
+
|
|
1077
|
+
<button onclick={() => open = !open}>
|
|
1078
|
+
Details
|
|
1079
|
+
<Icon name="chevronRight" chevronOpen={open} preset="muted" decorative />
|
|
1080
|
+
</button>
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
### Password visibility toggle
|
|
1084
|
+
|
|
1085
|
+
```svelte
|
|
1086
|
+
<script>
|
|
1087
|
+
import { Icon } from '@genarou/blazir-icons'
|
|
1088
|
+
let visible = $state(false)
|
|
1089
|
+
</script>
|
|
1090
|
+
|
|
1091
|
+
<div class="input-wrapper">
|
|
1092
|
+
<input type={visible ? 'text' : 'password'} />
|
|
1093
|
+
<button
|
|
1094
|
+
onclick={() => visible = !visible}
|
|
1095
|
+
aria-label={visible ? 'Hide password' : 'Show password'}
|
|
1096
|
+
>
|
|
1097
|
+
<Icon
|
|
1098
|
+
name={visible ? 'eyeOff' : 'eye'}
|
|
1099
|
+
preset="muted"
|
|
1100
|
+
effects={{ hoverScale: 1.1, cursor: 'pointer' }}
|
|
1101
|
+
decorative
|
|
1102
|
+
/>
|
|
1103
|
+
</button>
|
|
1104
|
+
</div>
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
### Notification bell with badge
|
|
1108
|
+
|
|
1109
|
+
```svelte
|
|
1110
|
+
<script>
|
|
1111
|
+
import { IconBadge } from '@genarou/blazir-icons'
|
|
1112
|
+
let count = $state(0)
|
|
1113
|
+
</script>
|
|
1114
|
+
|
|
1115
|
+
<button aria-label="Notifications ({count} unread)">
|
|
1116
|
+
<IconBadge
|
|
1117
|
+
name="bell"
|
|
1118
|
+
size={22}
|
|
1119
|
+
badge={count > 0 ? count : false}
|
|
1120
|
+
effects={{ wiggleOnHover: true, cursor: 'pointer' }}
|
|
1121
|
+
decorative
|
|
1122
|
+
/>
|
|
1123
|
+
</button>
|
|
1124
|
+
```
|
|
1125
|
+
|
|
1126
|
+
### Table row with hover-revealed actions
|
|
1127
|
+
|
|
1128
|
+
```svelte
|
|
1129
|
+
<script>
|
|
1130
|
+
import { Icon } from '@genarou/blazir-icons'
|
|
1131
|
+
let hovered = $state(false)
|
|
1132
|
+
const ctx = $derived({ hovered })
|
|
1133
|
+
</script>
|
|
1134
|
+
|
|
1135
|
+
<tr
|
|
1136
|
+
onmouseenter={() => hovered = true}
|
|
1137
|
+
onmouseleave={() => hovered = false}
|
|
1138
|
+
>
|
|
1139
|
+
<td>{row.name}</td>
|
|
1140
|
+
<td class="actions">
|
|
1141
|
+
<Icon name="edit" parentHoverContext={ctx} hoverColor="var(--primary)" preset="button" ariaLabel="Edit row" />
|
|
1142
|
+
<Icon name="trash" parentHoverContext={ctx} hoverColor="var(--danger-color)" preset="button" ariaLabel="Delete row" />
|
|
1143
|
+
</td>
|
|
1144
|
+
</tr>
|
|
1145
|
+
```
|
|
1146
|
+
|
|
1147
|
+
### Dynamic status icon
|
|
1148
|
+
|
|
1149
|
+
```svelte
|
|
1150
|
+
<script>
|
|
1151
|
+
import { Icon } from '@genarou/blazir-icons'
|
|
1152
|
+
import type { IconName } from '@genarou/blazir-icons'
|
|
1153
|
+
|
|
1154
|
+
type Status = 'success' | 'warning' | 'error' | 'loading'
|
|
1155
|
+
|
|
1156
|
+
const iconMap: Record<Status, IconName> = {
|
|
1157
|
+
success: 'circleCheck',
|
|
1158
|
+
warning: 'warning',
|
|
1159
|
+
error: 'error',
|
|
1160
|
+
loading: 'loadingDots',
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
export let status: Status = 'loading'
|
|
1164
|
+
</script>
|
|
1165
|
+
|
|
1166
|
+
<Icon
|
|
1167
|
+
name={iconMap[status]}
|
|
1168
|
+
variant={status === 'loading' ? 'muted' : status}
|
|
1169
|
+
spin={status === 'loading'}
|
|
1170
|
+
size={18}
|
|
1171
|
+
ariaLabel="Status: {status}"
|
|
1172
|
+
/>
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
### Preloading icons on route change (SvelteKit)
|
|
1176
|
+
|
|
1177
|
+
```ts
|
|
1178
|
+
// src/routes/dashboard/+page.ts
|
|
1179
|
+
import { preloadIcons } from '@genarou/blazir-icons'
|
|
1180
|
+
|
|
1181
|
+
export const load = async () => {
|
|
1182
|
+
// Icons are prefetched in background while page data loads
|
|
1183
|
+
preloadIcons(['chart', 'table', 'user', 'settings', 'logout', 'bell'])
|
|
1184
|
+
return {}
|
|
1185
|
+
}
|
|
1186
|
+
```
|
|
1187
|
+
|
|
1188
|
+
### Custom element with effects action
|
|
1189
|
+
|
|
1190
|
+
```svelte
|
|
1191
|
+
<script>
|
|
1192
|
+
import { iconEffects } from '@genarou/blazir-icons'
|
|
1193
|
+
import Check from '@genarou/blazir-icons/icons/Check'
|
|
1194
|
+
</script>
|
|
1195
|
+
|
|
1196
|
+
<div
|
|
1197
|
+
class="status-chip"
|
|
1198
|
+
use:iconEffects={{ pulse: true, hoverScale: 1.05, cursor: 'pointer' }}
|
|
1199
|
+
>
|
|
1200
|
+
<Check size={14} color="var(--success-color)" decorative />
|
|
1201
|
+
Active
|
|
1202
|
+
</div>
|
|
1203
|
+
```
|
|
1204
|
+
|
|
1205
|
+
---
|
|
1206
|
+
|