We are excited to announce @canonical/svelte-icons, a new library that brings icons from Pragma, Canonical’s new design system, to Svelte 5 as first-class components.
We are the Launchpad UI squad in the Web team, and we built this to support our own projects while making it available for the broader community.
Whether you are building products at Canonical or anywhere else, this library gives you instant access to our full icon set with modern Svelte 5 patterns and built-in performance optimizations.
Installation
bun add @canonical/svelte-icons
# or
npm install @canonical/svelte-icons
What’s Inside
Tree-Shakeable Icon Components
Every icon from @canonical/ds-assets is available as an individual Svelte component. Import only what you need:
<script>
import { HomeIcon, SettingsIcon, SearchIcon } from "@canonical/svelte-icons";
</script>
<HomeIcon />
<SettingsIcon class="custom-class" />
<SearchIcon style="color: red; width: 2em; height: 2em;" />
Icons inherit the current text color and font size by default, making them effortlessly adaptable to your UI context.
Built for Svelte 5
This library is built from the ground up with Svelte 5’s new runes syntax, using $props(), $derived, and $effect for clean, reactive icon management.
The library fully supports Server-Side Rendering (SSR) also fully functional without Javascript.
Performance: SVG Deduplication with IconsOptimizationProvider
The Problem
When you render the same icon multiple times, each instance includes the full SVG path data in the DOM. For pages with data tables, lists, or repeated UI patterns, this adds up fast.
The Solution
You can wrap your app (or any section) with IconsOptimizationProvider:
<script>
import { IconsOptimizationProvider, UserProfileIcon } from "@canonical/svelte-icons";
</script>
<IconsOptimizationProvider>
<nav><UserProfileIcon /></nav>
<main><UserProfileIcon /></main>
<footer><UserProfileIcon /></footer>
</IconsOptimizationProvider>
With the provider, multiple instances of the same icon share a single SVG <symbol> definition, and each instance references it via <use href="...">. Think of it like symbolic links in Unix: the icon definition exists once, and every usage is just a pointer to that definition. This significantly reduces DOM size when icons are repeated.
How It Works: Leader-Follower Pattern
Under the hood, IconsOptimizationProvider uses a leader-follower pattern:
- Each icon instance registers itself with the provider via Svelte context
- The first instance of each icon type becomes the “leader” and renders the
<symbol>definition - All instances reference the shared symbol
- When icons unmount, they unregister. If the leader unmounts, a new leader is elected automatically
This is fully reactive and handles dynamic mounting and unmounting of icons.
Icons Explorer: AI-Powered Search
We have built a comprehensive icons explorer in our Storybook that makes finding the right icon surprisingly easy.
LLM-Generated Metadata
At build time, we use Gemini 2.5 Flash to analyze each SVG and generate semantic tags. The model receives the icon name and SVG content, then returns contextual keywords.
For example, the instagram icon gets:
{
"instagram": {
"tags": ["instagram", "social media", "photo", "sharing", "app", "network", "camera", "brand", "logo", "platform", "photography"],
"file": "instagram.svg"
}
}
Fuzzy Search with Fuse.js
The explorer uses Fuse.js for fuzzy matching across icon names, file names, and LLM-generated tags:
const fuse = new Fuse(iconsWithMetadata, {
keys: ["name", "metadata.file", "metadata.tags"],
threshold: 0.2,
ignoreLocation: true,
findAllMatches: true,
isCaseSensitive: false,
});
This means you can search for “camera” and find the instagram icon, and related icons.
Interactive Tag Exploration
Click any tag in the icon detail modal to instantly filter by that term. Found an icon through “network”? Click the tag to see all network-related icons.
Build Pipeline
The library ships pre-built icon components generated from @canonical/ds-assets at build time. The build scripts are adaptable, so you can fork the repository and point them to your own SVG source if needed.
Custom Icons
In some cases you may need to use your own icons with the same optimization benefits. You can use IconBase directly:
<script>
import { IconBase, IconsOptimizationProvider } from "@canonical/svelte-icons";
</script>
<IconsOptimizationProvider>
<IconBase iconName="my-custom-icon">
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="6" stroke="currentColor" fill="none" />
</svg>
</IconBase>
</IconsOptimizationProvider>
The icons deduplication matches individual instances by the iconName, ensure its uniqueness to avoid collisions.
Try It Out
The library is available on NPM:
bun add @canonical/svelte-icons
Explore the full icon set and documentation in our Storybook: svelte-icons.canonical.com
Check out the source code: github.com/canonical/svelte-icons
We would love to hear your feedback. Open an issue, submit a PR, or reach out to the Web team.
Built with Svelte 5, Bun, Storybook 10, and a sprinkle of AI. Icons sourced from @canonical/ds-assets.



