Implementation of the Tabler Icons library for Svelte 5 applications using runes.
Browse all icons at tabler.io →
If you want to support our project and help us grow it, you can become a sponsor on GitHub or donate on PayPal.
npm install @tabler/icons-svelte-runesyarn add @tabler/icons-svelte-runespnpm add @tabler/icons-svelte-runesYou can also download the latest release from GitHub.
This package is built for Svelte 5 and uses the runes reactivity system ($props(), $derived). For Svelte 3 and 4 projects, use @tabler/icons-svelte instead.
The package is built with ES modules, so unused icons are tree-shaken from your bundle. Each icon is exported as a component.
<script lang="ts">
import { IconHeart } from '@tabler/icons-svelte-runes';
</script>
<IconHeart />Pass props to adjust the icon:
<IconHeart color="red" size={48} stroke={1.5} />| Name | Type | Default | Description |
|---|---|---|---|
size |
_number | string_ | 24 |
color |
string | currentColor | Stroke color for outline icons, fill color for filled icons |
stroke |
_number | string_ | 2 |
class |
string | – | Extra classes added to tabler-icon tabler-icon-{{name}} |
Any other attribute is forwarded to the rendered <svg> element.
Importing from the package root keeps your bundle small, because unused icons are removed. The bundler still has to compile every icon component (more than 6,000) before it can drop them, though, which slows down builds. To avoid that, import each icon from its own file:
<script lang="ts">
import IconHeart from '@tabler/icons-svelte-runes/icons/heart';
import IconHeartFilled from '@tabler/icons-svelte-runes/icons/heart-filled';
</script>
<IconHeart />
<IconHeartFilled />The path is the icon name in kebab-case, as listed on tabler.io/icons; filled icons end with -filled. Old icon names kept for backwards compatibility (aliases) are only exported from the package root.
With Vite 8 you can keep importing from the package root and let Rolldown skip compiling unused icons with lazy barrel optimization:
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
build: {
rolldownOptions: {
experimental: { lazyBarrel: true },
},
},
});The package includes full TypeScript definitions. Icons are typed as Svelte 5 Component<IconProps>:
import type { Icon } from '@tabler/icons-svelte-runes';
import { IconHeart } from '@tabler/icons-svelte-runes';
const MyIcon: Icon = IconHeart;When passing icons as props, use the Component type from Svelte:
<script lang="ts">
import type { Component } from 'svelte';
interface Props {
icon: Component<any>;
label: string;
}
let { icon: Icon, label }: Props = $props();
</script>
<button>
<Icon size={20} />
{label}
</button><script lang="ts">
import { IconHeart, IconStar, IconCircle } from '@tabler/icons-svelte-runes';
const icons = {
heart: IconHeart,
star: IconStar,
circle: IconCircle,
};
let selected = $state('heart');
let DynamicIcon = $derived(icons[selected]);
</script>
<DynamicIcon size={32} />
<button onclick={() => (selected = 'heart')}>Heart</button>
<button onclick={() => (selected = 'star')}>Star</button>
<button onclick={() => (selected = 'circle')}>Circle</button><script lang="ts">
import { IconHeart } from '@tabler/icons-svelte-runes';
let isLarge = $state(false);
let iconSize = $derived(isLarge ? 48 : 24);
</script>
<IconHeart size={iconSize} />
<button onclick={() => (isLarge = !isLarge)}>Toggle size</button>The API is identical, so only the package name changes:
- import { IconHeart } from '@tabler/icons-svelte';
+ import { IconHeart } from '@tabler/icons-svelte-runes';Internally this package uses $props() instead of export let and $derived for computed values, which makes it a better fit for Svelte 5's fine-grained reactivity.
Bug reports and icon requests are welcome in the issue tracker. Caught a mistake in this page? Edit it on GitHub.
Tabler Icons is licensed under the MIT License.