Files
lucide/packages/angular/MIGRATION.md
Karsa a0e202d759 feat(packages/angular): add new @lucide/angular package (#3897)
* Add new lucide angular package

* feat(packages/angular): added initial @lucide/angular package

* feat(packages/angular): update readme

* feat(packages/angular): update angular.json

* docs(packages/angular): added (for now) full documentation for @lucide/angular

* docs(packages/angular): added migration guide from lucide-angular

* fix(github): fix package label syntax 😅

* fix(lint): fix linting issues

* fix(github/angular): add prebuild stage

* fix(github/angular): add prebuild stage & fix tests

* fix(github/angular): fix LucideIconComponentType, update with _real_ public members

* fix(github/angular): add prebuild to build step manually

* fix(github/angular): downgrade vitest

* fix(packages/angular): fix migration guide code example

* fix(packages): add vitest + @vitest/* to pnpm overrides

* fix(packages): update pnpm-lock with merged version

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix(packages): fix aria-hidden logic

* fix(packages): update pnpm-lock

* fix(packages): extract vitest and jsdom to root devDependencies

* Fix copy utils script

* Format code

* feat(packages/angular): switched to self-describing IconData object from separate node+name – no more toKebabCase hackery
feat(packages/angular): renamed LucideIconComponentType => LucideIcon, and LucideIcon => LucideDynamicIcon
feat(packages/angular): added backwards compatible CSS class support
feat(packages/angular): switched to vector-effect: non-scaling-stroke implementation from computed stroke width
feat(packages/angular): rewrote icon provider to only accept a list of self-described icons – no more toKebabCase hackery & as an added bonus automatic backwards compatible alias support 🚀
feat(packages/angular): added legacy icon node helper function for passing legacy icons to providers
test(packages/angular): added unit tests on LUCIDE_CONFIG provider usage

* fix(packages/angular): fix linting issues

* feat(packages/angular): extract createLucideIcon logic into helper function, refactor export template to use the iconData object as defined in ExportTemplate

* Replace author

* Remove private field

* fix(packages/angular): remove createLucideIcon, it breaks the package :'(

* fix(packages/angular): fix rendering order of child elements (_before_ projected content)

* Format package.json

* Update docs/guide/packages/angular.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update packages/angular/MIGRATION.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-20 15:31:34 +01:00

4.6 KiB
Raw Blame History

Migrating from lucide-angular@lucide/angular

What changed

@lucide/angular moves from a module + single component based API to a more modern Angular approach:

  • The library defines modern signal-based, standalone components, without zone.js based change detection.
  • Icons are consumed as standalone imports (one component per icon).
  • Dynamic icon registration is done via provideLucideIcons(), not using NgModule.
  • Static icons use per-icon components for better tree-shaking.
  • Dynamic icons still use a single dynamic component (svg[lucideIcon]).
  • Global defaults are configured via provideLucideConfig().

Step 1 Update dependencies

Remove lucide-angular, add @lucide/angular, see http://lucide.dev/guide/packages/angular#installation


Step 2 Replace LucideAngularModule.pick(...) with provideLucideIcons(...)

Notes:

  • Old imports like AirVentIcon / AlarmClock from lucide-angular should be replaced with the new per-icon exports LucideAirVent and LucideAlarmClock.
  • If you mostly used static icons, you may not need to provide them at all, please refer to Step 3.

Before

NgModule based

import { BrowserModule, NgModule } from '@angular/core';
import { LucideAngularModule, AirVent, AlarmClock } from 'lucide-angular';

@NgModule({
  imports: [
    BrowserModule,
    LucideAngularModule.pick({ AirVent, AlarmClock }),
  ],
})
export class AppModule {}

Standalone

import { ApplicationConfig } from '@angular/core';
import { LucideAngularModule, AirVent, AlarmClock } from 'lucide-angular';

export const appConfig: ApplicationConfig = {
  providers: [
    // ...
    importProvidersFrom(LucideAngularModule.pick({ AirVent, AlarmClock })),
  ]
};

After

import { ApplicationConfig } from '@angular/core';
import { provideLucideIcons, LucideAirVent, LucideAlarmClock } from '@lucide/angular';

export const appConfig: ApplicationConfig = {
  providers: [
    // ...
    provideLucideIcons(
      LucideAirVent,
      LucideAlarmClock,
    ),
  ]
};

Step 3 Replace <lucide-angular> / <lucide-icon> / <i-lucide> / <span-lucide>

The legacy package rendered everything through a single component. All of these selectors must be migrated to <svg> usage.

A. Static icons by name

If the icon is known at build time, just use a static import:

Before

<lucide-angular name="circle-check"></lucide-angular>

After

<svg lucideCircleCheck></svg>

B. Static icons with icon data binding

Before

import { CircleCheck } from 'lucide-angular';
<lucide-icon [img]="CircleCheck"></lucide-icon>

After

import { LucideCircleCheck } from '@lucide/angular';
<svg lucideCircleCheck></svg>

...and import LucideCircleCheck from @lucide/angular.


C. Dynamic icons

If the icon varies at runtime, use the dynamic component:

Before

<lucide-icon [name]="item.icon"></lucide-icon>

After

<svg [lucideIcon]="item.icon"></svg>

Step 4 Replace LucideIconConfig with provideLucideConfig()

Before

import { inject } from '@angular/core';
import { LucideIconConfig } from 'lucide-angular';

inject(LucideIconConfig).size = 12;

After

import { provideLucideConfig } from '@lucide/angular';

providers: [
  provideLucideConfig({ size: 12 }),
]

Where to place it

  • App-wide: AppModule.providers or bootstrapApplication(...providers)
  • Feature-level: feature module providers
  • Component-level (standalone): component providers

Troubleshooting

The icon is not being displayed

If using per-icon-components:

  1. Ensure that the icon component is being imported, if using per-icon-components
  2. Check that the icon name matches exactly (case-sensitive)

If using the dynamic component:

  1. Ensure the icon is provided via provideLucideIcons() if using string names
  2. Verify the icon is imported from @lucide/angular and not the legacy package

TypeScript errors?

Make sure you're importing from @lucide/angular and not lucide-angular.

Icons render with wrong defaults

Ensure provideLucideConfig() is used at the right level.


TL;DR

  • LucideAngularModule ⇒ static: removed; dynamic: LucideIcon
  • LucideAngularModule.pick(...)provideLucideIcons(...)
  • <lucide-angular name="foo-bar"><svg lucideFooBar>
  • <lucide-icon [name]="expr"><svg [lucideIcon]="expr">
  • <lucide-icon [img]="expr"><svg [lucideIcon]="expr">
  • LucideIconConfigprovideLucideConfig(...)