Introducing Canonical Svelte Icons Library

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:

  1. Each icon instance registers itself with the provider via Svelte context
  2. The first instance of each icon type becomes the “leader” and renders the <symbol> definition
  3. All instances reference the shared symbol
  4. 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.

4 Likes

Thank you for sharing the Canonical Svelte Icons Library with the community! I really appreciate you making this icon set available for everyone to use and benefit from. It’s great to see high-quality, Svelte-ready icons being provided openly — thank you for your hard work and for contributing this valuable resource to all users!

Any chance of making that Icon library a Debian-style package for integration into older distros, to facilitate the migration process via gradual incorporation within older infrastructure before “failover” to newer distro releases? Just a thought. :slight_smile:

Since @canonical/svelte-icons is a web technology based library it is intended to be bundled into a website or a web application during the build process (rather than a system-level utility).
The icons are intended to be distributed via NPM/Bun and consumed by Svelte v5 alongwith SvelteKit, Astro or Tauri..

1 Like

Including that with the web-technology based library … does not negate the possibility, nor the advantages, of it also being available as a less-restrictive universal-access technology, by being deployed, in parallel, as a standalone Debian package.

I would encourage you to consider that different perspective, an ask that your build-process include a parallel process for the Debian-package build.

Thank you in advance for that consideration … however the outcome. :slight_smile:

2 Likes