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