0
# Svelte Components
1
2
Svelte component library providing tree-shakable components for all 5,945 Tabler Icons with full TypeScript support. Each icon is available as an optimized Svelte component with reactive props and consistent interfaces.
3
4
## Package Information
5
6
- **Package Name**: @tabler/icons-svelte
7
- **Installation**: `npm install @tabler/icons-svelte`
8
- **Peer Dependencies**: Svelte >= 3 < 6 || >= 5.0.0-next.0
9
10
## Core Imports
11
12
```typescript
13
import { IconHome, IconHeart, IconArrowLeft } from '@tabler/icons-svelte';
14
```
15
16
## Capabilities
17
18
### Icon Component Import
19
20
Tree-shakable imports for individual icon components with full TypeScript support and Svelte reactivity.
21
22
```typescript { .api }
23
/**
24
* Individual icon component imports
25
* Pattern: Icon{PascalCaseName} for outline icons
26
* Pattern: Icon{PascalCaseName}Filled for filled icons
27
*/
28
import { IconHome } from '@tabler/icons-svelte';
29
import { IconHeart } from '@tabler/icons-svelte';
30
import { IconHeartFilled } from '@tabler/icons-svelte';
31
import { IconArrowLeft } from '@tabler/icons-svelte';
32
33
interface IconProps {
34
/** Icon size in pixels (applies to both width and height) */
35
size?: number;
36
/** Icon stroke color (outline icons) or fill color (filled icons) */
37
color?: string;
38
/** Stroke width for outline icons */
39
stroke?: number;
40
/** CSS class name */
41
class?: string;
42
}
43
```
44
45
**Usage Examples:**
46
47
```svelte
48
<script lang="ts">
49
import { IconHome, IconHeart, IconArrowLeft } from '@tabler/icons-svelte';
50
51
let iconSize = 24;
52
let heartColor = 'red';
53
let isActive = false;
54
</script>
55
56
<main>
57
<!-- Basic usage -->
58
<IconHome />
59
60
<!-- With custom props -->
61
<IconHeart
62
size={32}
63
color={heartColor}
64
stroke={1.5}
65
class="heart-icon"
66
/>
67
68
<!-- With reactive props -->
69
<IconArrowLeft
70
size={iconSize}
71
color={isActive ? 'blue' : 'gray'}
72
on:click={() => history.back()}
73
/>
74
75
<!-- With dynamic class -->
76
<IconHome
77
class={isActive ? 'active' : 'inactive'}
78
size={isActive ? 32 : 24}
79
/>
80
</main>
81
82
<style>
83
.heart-icon {
84
cursor: pointer;
85
transition: transform 0.2s;
86
}
87
88
.heart-icon:hover {
89
transform: scale(1.1);
90
}
91
92
.active {
93
color: #3b82f6;
94
}
95
96
.inactive {
97
color: #6b7280;
98
}
99
</style>
100
```
101
102
### Icon Component Props
103
104
Comprehensive prop interface for customizing icon appearance and behavior with Svelte reactivity.
105
106
```typescript { .api }
107
interface IconProps {
108
/**
109
* Icon size in pixels (applies to both width and height)
110
* @default 24
111
*/
112
size?: number;
113
114
/**
115
* Icon stroke color (outline icons) or fill color (filled icons)
116
* @default "currentColor"
117
*/
118
color?: string;
119
120
/**
121
* Stroke width for outline icons
122
* @default 2
123
*/
124
stroke?: number;
125
126
/**
127
* CSS class name applied to the SVG element
128
* Can be reactive
129
*/
130
class?: string;
131
}
132
133
// Event handlers (available on all icon components)
134
interface IconEvents {
135
/** Click event handler */
136
on:click?: (event: MouseEvent) => void;
137
/** Mouse enter event handler */
138
on:mouseenter?: (event: MouseEvent) => void;
139
/** Mouse leave event handler */
140
on:mouseleave?: (event: MouseEvent) => void;
141
}
142
```
143
144
**Usage Examples:**
145
146
```svelte
147
<script lang="ts">
148
import { IconUser, IconSettings, IconHome } from '@tabler/icons-svelte';
149
150
let dynamicSize = 24;
151
let strokeWidth = 2;
152
let themeColor = '#3b82f6';
153
let isHovered = false;
154
let isError = false;
155
156
function handleClick() {
157
console.log('Icon clicked');
158
}
159
160
function handleHover() {
161
isHovered = true;
162
}
163
164
function handleLeave() {
165
isHovered = false;
166
}
167
</script>
168
169
<div>
170
<!-- Size variations -->
171
<IconUser size={16} /> <!-- Small -->
172
<IconUser size={24} /> <!-- Default -->
173
<IconUser size={32} /> <!-- Large -->
174
<IconUser size={dynamicSize} /> <!-- Reactive -->
175
176
<!-- Color variations -->
177
<IconSettings color="#3b82f6" />
178
<IconSettings color="rgb(239, 68, 68)" />
179
<IconSettings color={themeColor} />
180
181
<!-- Stroke width variations -->
182
<IconHome stroke={1} /> <!-- Thin -->
183
<IconHome stroke={3} /> <!-- Thick -->
184
<IconHome stroke={strokeWidth} /> <!-- Reactive -->
185
186
<!-- CSS classes -->
187
<IconSettings class="settings-icon rotating" />
188
<IconSettings class={isHovered ? 'hovered' : ''} />
189
190
<!-- Event handlers -->
191
<IconSettings
192
on:click={handleClick}
193
on:mouseenter={handleHover}
194
on:mouseleave={handleLeave}
195
class={isHovered ? 'hovered' : ''}
196
/>
197
198
<!-- Conditional styling -->
199
<IconSettings
200
color={isError ? 'red' : 'blue'}
201
size={isError ? 32 : 24}
202
class={isError ? 'error' : 'normal'}
203
/>
204
</div>
205
206
<style>
207
.settings-icon {
208
cursor: pointer;
209
transition: transform 0.2s;
210
}
211
212
.rotating {
213
animation: spin 2s linear infinite;
214
}
215
216
.hovered {
217
transform: scale(1.1);
218
}
219
220
.error {
221
filter: drop-shadow(0 0 4px red);
222
}
223
224
@keyframes spin {
225
from { transform: rotate(0deg); }
226
to { transform: rotate(360deg); }
227
}
228
</style>
229
```
230
231
### Outline vs Filled Variants
232
233
Access to both outline (stroke-based) and filled (solid) icon variants with different naming conventions.
234
235
```typescript { .api }
236
/**
237
* Icon naming conventions:
238
* - Outline icons: Icon{PascalCaseName} (default style)
239
* - Filled icons: Icon{PascalCaseName}Filled
240
*
241
* Examples:
242
* - IconHome (outline) vs IconHomeFilled (filled)
243
* - IconHeart (outline) vs IconHeartFilled (filled)
244
* - IconStar (outline) vs IconStarFilled (filled)
245
*/
246
247
// Outline icons (4,964 available)
248
import {
249
IconHome,
250
IconHeart,
251
IconStar,
252
IconUser,
253
IconSettings
254
} from '@tabler/icons-svelte';
255
256
// Filled icons (981 available)
257
import {
258
IconHomeFilled,
259
IconHeartFilled,
260
IconStarFilled,
261
IconUserFilled,
262
IconSettingsFilled
263
} from '@tabler/icons-svelte';
264
```
265
266
**Usage Examples:**
267
268
```svelte
269
<script lang="ts">
270
import {
271
IconHeart,
272
IconHeartFilled,
273
IconStar,
274
IconStarFilled,
275
IconCheckCircle,
276
IconCheckCircleFilled
277
} from '@tabler/icons-svelte';
278
279
let isFavorite = false;
280
let rating = 0;
281
let isCompleted = false;
282
283
function toggleFavorite() {
284
isFavorite = !isFavorite;
285
}
286
287
function setRating(value: number) {
288
rating = value;
289
}
290
</script>
291
292
<div>
293
<!-- Toggle between outline and filled -->
294
<button on:click={toggleFavorite}>
295
{#if isFavorite}
296
<IconHeartFilled color="red" />
297
{:else}
298
<IconHeart color="gray" />
299
{/if}
300
{isFavorite ? 'Favorited' : 'Favorite'}
301
</button>
302
303
<!-- Star rating component -->
304
<div class="rating">
305
{#each [1, 2, 3, 4, 5] as value}
306
<button on:click={() => setRating(value)}>
307
{#if value <= rating}
308
<IconStarFilled color="gold" />
309
{:else}
310
<IconStar color="gray" />
311
{/if}
312
</button>
313
{/each}
314
</div>
315
316
<!-- Conditional icon rendering -->
317
{#if isCompleted}
318
<IconCheckCircleFilled color="green" />
319
{:else}
320
<IconCheckCircle color="gray" />
321
{/if}
322
</div>
323
324
<style>
325
.rating {
326
display: flex;
327
gap: 0.25rem;
328
}
329
330
.rating button {
331
background: none;
332
border: none;
333
cursor: pointer;
334
padding: 0.25rem;
335
border-radius: 0.25rem;
336
transition: background-color 0.2s;
337
}
338
339
.rating button:hover {
340
background-color: #f3f4f6;
341
}
342
</style>
343
```
344
345
### Reactive Store Integration
346
347
Deep integration with Svelte stores for reactive icon properties and global state management.
348
349
```typescript { .api }
350
/**
351
* Svelte stores integration patterns
352
* Icons work seamlessly with writable, readable, and derived stores
353
*/
354
355
import { writable, derived } from 'svelte/store';
356
357
// Theme store example
358
const theme = writable('light');
359
const iconColor = derived(theme, $theme => $theme === 'dark' ? '#ffffff' : '#000000');
360
const iconSize = derived(theme, $theme => $theme === 'dark' ? 28 : 24);
361
362
// Animation store example
363
const isAnimating = writable(false);
364
const rotation = writable(0);
365
```
366
367
**Usage Examples:**
368
369
```svelte
370
<script lang="ts">
371
import { writable, derived } from 'svelte/store';
372
import {
373
IconSun,
374
IconMoon,
375
IconLoader,
376
IconCheck,
377
IconX,
378
IconClock
379
} from '@tabler/icons-svelte';
380
381
// Theme store
382
const isDark = writable(false);
383
const iconColor = derived(isDark, $isDark => $isDark ? '#ffffff' : '#000000');
384
const iconSize = derived(isDark, $isDark => $isDark ? 28 : 24);
385
386
function toggleTheme() {
387
isDark.update(dark => !dark);
388
}
389
390
// Loading state store
391
const isLoading = writable(false);
392
const rotation = writable(0);
393
394
// Auto-rotate when loading
395
$: if ($isLoading) {
396
const interval = setInterval(() => {
397
rotation.update(r => r + 90);
398
}, 200);
399
400
// Cleanup when not loading
401
const unsubscribe = isLoading.subscribe(loading => {
402
if (!loading) {
403
clearInterval(interval);
404
unsubscribe();
405
}
406
});
407
}
408
409
// Status store
410
const status = writable('pending'); // 'success' | 'error' | 'pending'
411
const statusIcon = derived(status, $status => {
412
switch ($status) {
413
case 'success': return IconCheck;
414
case 'error': return IconX;
415
default: return IconClock;
416
}
417
});
418
const statusColor = derived(status, $status => {
419
switch ($status) {
420
case 'success': return 'green';
421
case 'error': return 'red';
422
default: return 'gray';
423
}
424
});
425
</script>
426
427
<div>
428
<!-- Theme-aware icons -->
429
<button on:click={toggleTheme}>
430
{#if $isDark}
431
<IconMoon color={$iconColor} size={$iconSize} />
432
{:else}
433
<IconSun color={$iconColor} size={$iconSize} />
434
{/if}
435
Toggle Theme
436
</button>
437
438
<!-- Animated loading icon -->
439
<IconLoader
440
style="transform: rotate({$rotation}deg); transition: transform 0.5s ease"
441
class={$isLoading ? 'spinning' : ''}
442
/>
443
444
<!-- Status-based icons -->
445
<svelte:component
446
this={$statusIcon}
447
color={$statusColor}
448
size={24}
449
/>
450
</div>
451
452
<style>
453
.spinning {
454
animation: spin 1s linear infinite;
455
}
456
457
@keyframes spin {
458
from { transform: rotate(0deg); }
459
to { transform: rotate(360deg); }
460
}
461
</style>
462
```
463
464
### Component Composition Patterns
465
466
Advanced patterns for composing icon components with other Svelte components and logic.
467
468
```typescript { .api }
469
/**
470
* Component composition patterns
471
* Creating reusable icon-based components with slots and props
472
*/
473
474
// Icon button component interface
475
interface IconButtonProps {
476
icon: any; // Svelte component
477
variant?: 'primary' | 'secondary' | 'ghost';
478
size?: 'sm' | 'md' | 'lg';
479
disabled?: boolean;
480
}
481
482
// Icon with tooltip interface
483
interface IconTooltipProps {
484
icon: any;
485
tooltip: string;
486
position?: 'top' | 'bottom' | 'left' | 'right';
487
}
488
```
489
490
**Usage Examples:**
491
492
```svelte
493
<!-- IconButton.svelte -->
494
<script lang="ts">
495
export let icon: any;
496
export let variant: 'primary' | 'secondary' | 'ghost' = 'primary';
497
export let size: 'sm' | 'md' | 'lg' = 'md';
498
export let disabled = false;
499
500
$: iconSize = size === 'sm' ? 16 : size === 'lg' ? 24 : 20;
501
$: buttonClass = `btn btn-${variant} btn-${size}`;
502
</script>
503
504
<button
505
class={buttonClass}
506
{disabled}
507
on:click
508
>
509
<svelte:component this={icon} size={iconSize} />
510
<slot />
511
</button>
512
513
<style>
514
.btn {
515
display: flex;
516
align-items: center;
517
gap: 0.5rem;
518
padding: 0.5rem 1rem;
519
border: none;
520
border-radius: 0.25rem;
521
cursor: pointer;
522
transition: all 0.2s;
523
}
524
525
.btn:disabled {
526
opacity: 0.5;
527
cursor: not-allowed;
528
}
529
530
.btn-primary {
531
background-color: #3b82f6;
532
color: white;
533
}
534
535
.btn-secondary {
536
background-color: #6b7280;
537
color: white;
538
}
539
540
.btn-ghost {
541
background-color: transparent;
542
color: currentColor;
543
}
544
545
.btn-sm {
546
padding: 0.25rem 0.5rem;
547
font-size: 0.875rem;
548
}
549
550
.btn-lg {
551
padding: 0.75rem 1.5rem;
552
font-size: 1.125rem;
553
}
554
</style>
555
556
<!-- Usage of IconButton -->
557
<script lang="ts">
558
import IconButton from './IconButton.svelte';
559
import { IconTrash, IconEdit, IconPlus } from '@tabler/icons-svelte';
560
561
function handleAdd() {
562
console.log('Add clicked');
563
}
564
565
function handleEdit() {
566
console.log('Edit clicked');
567
}
568
569
function handleDelete() {
570
console.log('Delete clicked');
571
}
572
</script>
573
574
<div class="actions">
575
<IconButton icon={IconPlus} variant="primary" on:click={handleAdd}>
576
Add Item
577
</IconButton>
578
579
<IconButton icon={IconEdit} variant="secondary" on:click={handleEdit}>
580
Edit
581
</IconButton>
582
583
<IconButton icon={IconTrash} variant="ghost" on:click={handleDelete}>
584
Delete
585
</IconButton>
586
</div>
587
588
<style>
589
.actions {
590
display: flex;
591
gap: 0.5rem;
592
}
593
</style>
594
```
595
596
### Dynamic Icon Loading
597
598
Load icons dynamically based on string identifiers with TypeScript safety and performance optimization.
599
600
```svelte
601
<script lang="ts">
602
import type { ComponentType } from 'svelte';
603
604
// Icon registry for dynamic loading
605
const iconRegistry: Record<string, () => Promise<{ default: ComponentType }>> = {
606
home: () => import('@tabler/icons-svelte').then(mod => ({ default: mod.IconHome })),
607
user: () => import('@tabler/icons-svelte').then(mod => ({ default: mod.IconUser })),
608
settings: () => import('@tabler/icons-svelte').then(mod => ({ default: mod.IconSettings })),
609
};
610
611
export let iconName: string;
612
export let size = 24;
613
export let color = 'currentColor';
614
615
let IconComponent: ComponentType | null = null;
616
let loading = false;
617
let error = false;
618
619
$: loadIcon(iconName);
620
621
async function loadIcon(name: string) {
622
if (!iconRegistry[name]) {
623
error = true;
624
return;
625
}
626
627
loading = true;
628
error = false;
629
630
try {
631
const module = await iconRegistry[name]();
632
IconComponent = module.default;
633
} catch (err) {
634
error = true;
635
console.warn(`Failed to load icon: ${name}`, err);
636
} finally {
637
loading = false;
638
}
639
}
640
</script>
641
642
{#if loading}
643
<div class="icon-placeholder loading" style="width: {size}px; height: {size}px;" />
644
{:else if error}
645
<div class="icon-placeholder error" style="width: {size}px; height: {size}px;" />
646
{:else if IconComponent}
647
<svelte:component this={IconComponent} {size} {color} />
648
{/if}
649
650
<style>
651
.icon-placeholder {
652
display: inline-block;
653
border-radius: 0.25rem;
654
animation: pulse 1.5s ease-in-out infinite;
655
}
656
657
.loading {
658
background-color: #e5e7eb;
659
}
660
661
.error {
662
background-color: #fca5a5;
663
}
664
665
@keyframes pulse {
666
0%, 100% { opacity: 1; }
667
50% { opacity: 0.5; }
668
}
669
</style>
670
```
671
672
## Common Usage Patterns
673
674
### Icon Animation Components
675
676
Create animated icon components using Svelte's built-in animation capabilities.
677
678
```svelte
679
<script lang="ts">
680
import { fade, scale, fly } from 'svelte/transition';
681
import { IconCheck, IconX, IconLoader } from '@tabler/icons-svelte';
682
683
export let status: 'loading' | 'success' | 'error' = 'loading';
684
export let size = 24;
685
686
$: icon = status === 'success' ? IconCheck :
687
status === 'error' ? IconX :
688
IconLoader;
689
690
$: color = status === 'success' ? 'green' :
691
status === 'error' ? 'red' :
692
'gray';
693
</script>
694
695
<div class="status-icon">
696
{#key status}
697
<svelte:component
698
this={icon}
699
{size}
700
{color}
701
class={status === 'loading' ? 'spinning' : ''}
702
in:scale={{ duration: 300 }}
703
out:fade={{ duration: 200 }}
704
/>
705
{/key}
706
</div>
707
708
<style>
709
.status-icon {
710
display: inline-block;
711
}
712
713
.spinning {
714
animation: spin 1s linear infinite;
715
}
716
717
@keyframes spin {
718
from { transform: rotate(0deg); }
719
to { transform: rotate(360deg); }
720
}
721
</style>
722
```
723
724
### Icon Grid Component
725
726
Create icon grid interfaces for icon selection and display.
727
728
```svelte
729
<script lang="ts">
730
import * as TablerIcons from '@tabler/icons-svelte';
731
732
export let selectedIcon: string | null = null;
733
export let onSelect: (iconName: string) => void = () => {};
734
735
// Get all available icons
736
const iconEntries = Object.entries(TablerIcons).filter(([name]) =>
737
name.startsWith('Icon') && !name.includes('Filled')
738
);
739
740
function handleIconClick(iconName: string) {
741
selectedIcon = iconName;
742
onSelect(iconName);
743
}
744
</script>
745
746
<div class="icon-grid">
747
{#each iconEntries as [iconName, IconComponent]}
748
<button
749
class="icon-card"
750
class:selected={selectedIcon === iconName}
751
on:click={() => handleIconClick(iconName)}
752
>
753
<svelte:component this={IconComponent} size={32} />
754
<span class="icon-name">{iconName.replace('Icon', '')}</span>
755
</button>
756
{/each}
757
</div>
758
759
<style>
760
.icon-grid {
761
display: grid;
762
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
763
gap: 0.5rem;
764
padding: 1rem;
765
}
766
767
.icon-card {
768
display: flex;
769
flex-direction: column;
770
align-items: center;
771
gap: 0.5rem;
772
padding: 1rem;
773
background: white;
774
border: 1px solid #e5e7eb;
775
border-radius: 0.5rem;
776
cursor: pointer;
777
transition: all 0.2s;
778
}
779
780
.icon-card:hover {
781
background-color: #f9fafb;
782
transform: translateY(-2px);
783
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
784
}
785
786
.icon-card.selected {
787
border-color: #3b82f6;
788
background-color: #eff6ff;
789
}
790
791
.icon-name {
792
font-size: 0.875rem;
793
text-align: center;
794
color: #6b7280;
795
}
796
</style>
797
```