Documentation

Use the 3,504 icons in 4 styles with your framework, from a CDN, or as plain SVG.

Getting started

Healing Icons has 3,504 icons in 4 styles. Pick the package for your stack: every package has the same icons, names and options.

Icon names are English kebab-case, like arrow-left. Components use PascalCase with an Icon suffix: ArrowLeftIcon (names that start with a digit get a prefix instead: Icon2fa). Find names with the search on the icon library, or press Ctrl K there.

Styles

outline
outline-duo
fill
glyph-duo

Every package exposes the styles as entry points: …/outline (the default), …/outline-duo, …/fill and …/glyph-duo. Icons are drawn on an 18 × 18 grid; outline icons use a 1.5 stroke.

Single-color icons use currentColor, so they follow the text color unless you set color. Duo styles have a second layer you can recolor with secondaryColor.

React

Like.jsx
import { HeartIcon } from "@healing-icons/react";              // outline (default)
import { HeartIcon as HeartFill } from "@healing-icons/react/fill";

export function Like({ liked }) {
  return liked ? <HeartFill color="tomato" title="Liked" /> : <HeartIcon size={20} />;
}

Each icon is its own module, so bundlers only ship the icons you import. You can also import a single file: import HeartIcon from "@healing-icons/react/outline/HeartIcon". Components forward ref and pass other props (className, onClick, aria-*) to the <svg>. They work in Server Components.

Vue

Like.vue
<script setup>
import { HeartIcon } from "@healing-icons/vue";
import { HeartIcon as HeartFill } from "@healing-icons/vue/fill";
defineProps(["liked"]);
</script>

<template>
  <HeartFill v-if="liked" color="tomato" title="Liked" />
  <HeartIcon v-else :size="20" :stroke-width="2" />
</template>

Vue 3.3 or newer. Props can be written in kebab-case (secondary-color, stroke-width). class, style and listeners such as @click fall through to the <svg>.

Svelte

Like.svelte
<script>
  import HeartIcon from "@healing-icons/svelte/outline/HeartIcon";
  import HeartFill from "@healing-icons/svelte/fill/HeartIcon";

  let { liked } = $props();
</script>

{#if liked}
  <HeartFill color="tomato" title="Liked" />
{:else}
  <HeartIcon size={20} />
{/if}

Svelte 5. Single-icon imports (…/<style>/<Component>) are the fastest, in dev and in builds. Named imports such as import { HeartIcon } from "@healing-icons/svelte/fill" also work and are tree-shaken, but make the Vite dev server process the whole style once.

Angular

like.component.ts
import { Component, input } from "@angular/core";
import { HealingIcon, HeartIcon } from "@healing-icons/angular";
import { HeartIcon as HeartFill } from "@healing-icons/angular/fill";

@Component({
  selector: "app-like",
  imports: [HealingIcon],
  template: `
    @if (liked()) {
      <healing-icon [icon]="HeartFill" color="tomato" title="Liked" />
    } @else {
      <healing-icon [icon]="HeartIcon" [size]="20" />
    }
  `,
})
export class LikeComponent {
  readonly liked = input(false);
  protected readonly HeartIcon = HeartIcon;
  protected readonly HeartFill = HeartFill;
}

Angular 17 or newer. <healing-icon> is a standalone component; icons are plain data, so only the ones you import end up in the build. It supports server rendering (hydration skips the icon and re-creates it on the client).

React Native

With Expo, install the renderer with npx expo install react-native-svg.

Like.tsx
import HeartIcon from "@healing-icons/react-native/outline/HeartIcon";
import HeartFill from "@healing-icons/react-native/fill/HeartIcon";

export function Like({ liked }: { liked: boolean }) {
  return liked ? <HeartFill color="tomato" title="Liked" /> : <HeartIcon size={20} color="#14201b" />;
}

React Native has no inherited text color, so color defaults to black. Metro doesn't tree-shake, so prefer single-icon imports as above. title becomes the accessibility label; other react-native-svg props (style, onPress, testID) go to the <Svg>.

Web Components

<healing-icon> works in plain HTML and in any framework. The quickest start is a CDN: the lazy build loads each icon the first time it's used.

index.html
<script type="module" src="https://cdn.jsdelivr.net/npm/@healing-icons/elements/dist/lazy.js"></script>

<healing-icon name="heart"></healing-icon>
<healing-icon name="heart" variant="fill" size="32" color="tomato" label="Liked"></healing-icon>

With a bundler, install the package and import the icons you use:

main.js
import "@healing-icons/elements";
import "@healing-icons/elements/outline/heart";   // registers <healing-icon name="heart">
import "@healing-icons/elements/fill/star";       // registers <healing-icon name="star" variant="fill">

Attributes mirror the component props in kebab-case (secondary-color, stroke-width, absolute-stroke-width); use label for an accessible name. The icon renders in a shadow root; style it with healing-icon::part(svg). In Vue, mark it as a custom element (compilerOptions.isCustomElement); in Angular, add CUSTOM_ELEMENTS_SCHEMA.

SVG files, CDN and sprites

The healing-icons package has the optimized SVG files, at healing-icons/svg/<style>/<name>.svg.

any bundler
import heartUrl from "healing-icons/svg/outline/heart.svg";

<img src={heartUrl} width="24" height="24" alt="" />

Every file is also on jsDelivr and unpkg. Pin a version in production. An <img> can't follow the text color; use the icon as a CSS mask for that:

CDN
<img src="https://cdn.jsdelivr.net/npm/healing-icons@0.7/svg/outline/heart.svg" width="24" height="24" alt="">

<style>
  .icon-heart {
    width: 24px; height: 24px;
    background: currentColor;
    mask: url(https://cdn.jsdelivr.net/npm/healing-icons@0.7/svg/outline/heart.svg) center / contain no-repeat;
  }
</style>

Sprites put many icons in one file. Build one with just the icons you need, then reference them with <use>:

terminal
npx healing-icons sprite heart star arrow-left --style outline --out public/icons.svg
index.html
<svg width="24" height="24"><use href="/icons.svg#heart"/></svg>

On the icon library, Select icons to download them as a ZIP of SVG files or as a sprite.

Editor and design tools

  • VS Code

    Search icons with previews and insert them as code for the file you're in (Ctrl Alt I), with the import added. Hover an icon name to see it.

terminal
code --install-extension hoanghuilinh.healing-icons-vscode

Props

The same options in every package. React Native accepts numbers only for size; the web component takes them as kebab-case attributes.

PropDefaultDescription
size24Width and height (number or CSS length)
colorcurrentColorIcon color; single-color icons follow the text color
secondaryColorcolorColor of the second layer of duo icons
strokeWidth1.5Stroke width of outline icons, in grid units (18 per icon)
absoluteStrokeWidthfalseTreat strokeWidth as pixels, the same at every size
titleAccessible name; without it the icon is hidden from screen readers

Icon names from data

Every package exports an IconName type (a union of all names) and IconStyle. When the icon is only known at runtime (CMS, config), DynamicIcon loads it on demand:

React
import { DynamicIcon, type IconName } from "@healing-icons/react/dynamic";

function MenuItem({ icon, label }: { icon: IconName; label: string }) {
  return (
    <li>
      <DynamicIcon name={icon} variant="fill" fallback={<span className="size-6" />} />
      {label}
    </li>
  );
}

Vue and Svelte: DynamicIcon from …/dynamic (with a fallback slot / snippet). Angular: <healing-dynamic-icon [name]="…"> from @healing-icons/angular/dynamic. Web component: the lazy build always loads by name.

Prefer static imports when you can. With DynamicIcon, every icon becomes a lazy chunk of your build (React Native's Metro bundles all of them), and showing one costs an extra request.

Accessibility

Icons are decorative by default: they're hidden from screen readers (aria-hidden). When an icon carries meaning on its own, give it a title (label on the web component) and it becomes an image with that name.

React
// Icon-only button: name the button, keep the icon decorative.
<button aria-label="Delete"><TrashIcon /></button>

// Icon that stands alone
<WarningIcon title="Warning" color="#b45309" />