Icon
Renders an SVG icon by name, resolved against the provider configured with IconProvider.
Interactive example
Installation
npm install @morphos/iconspnpm add @morphos/iconsyarn add @morphos/iconsbun add @morphos/iconsImport
import { Icon } from '@morphos/icons'Usage
Icon resolves name against whichever provider is currently configured. That provider is set
with IconProvider, which is mandatory — every app applies it once, at
the root, before any Icon renders:
import { Icon, IconProvider } from '@morphos/icons'
import { LucideSource } from '@morphos/icons/lucide'
import { Component } from '@praxisjs/decorators'
import { StatefulComponent } from '@praxisjs/core'
@IconProvider(LucideSource)
@Component()
class App extends StatefulComponent {
render() {
return <Icon name="Plus" aria-label="Add item" />
}
}LucideSource is the built-in provider — a pre-configured wrapper around lucide
(an optional peer dependency; install it only if you use this provider). It lives in its own entry,
@morphos/icons/lucide, so apps that use only their own icon set never import lucide. It still
has to be applied through IconProvider explicitly, like any other provider — there is no default.
npm install lucidepnpm add lucideyarn add lucidebun add lucideOnce you import LucideSource from @morphos/icons/lucide, your editor autocompletes every lucide
name on name — nothing else to set up. Any other string is still accepted, for names from your own
providers.
Overriding the provider per instance
Once IconProvider has configured an app-wide provider, every Icon without a provider prop
resolves against it. Pass provider to resolve a single icon against a different,
already-registered provider instead:
<Icon name="logo" provider="brand" />See IconProvider for registering a custom provider
like "brand".
Props
| Prop | Type | Default | Description |
|---|---|---|---|
name | LucideIconName | string | — | Icon name, resolved against the configured provider. Required. |
provider | "lucide" | string | configured provider | Overrides the configured provider for this instance only. |
size | number | string | 24 | Applied to both width and height. |
color | string | "currentColor" | Icon color — stroke for a structured (nodes) provider like lucide, or whatever the source markup itself declares for an { svg } provider. |
strokeWidth | number | string | 2 | Structured (nodes) providers only. |
absoluteStrokeWidth | boolean | false | Structured (nodes) providers only — scales strokeWidth so the visual stroke thickness stays constant across sizes. |
style | string | CSSProperties | — | Inline style on the root <svg>. |
class | string | — | CSS class on the root <svg>. |
id | string | — | id on the root element. |
aria-label | string | — | Accessible name. When set, the icon gets role="img"; otherwise it's aria-hidden. |
Accessibility
Icons are decorative by default: aria-hidden="true" and no role. Pass aria-label when the
icon conveys meaning on its own — an icon-only button with no visible text, for example — and
Icon switches to role="img" with that label instead of hiding itself.
Bundle size
Resolving by name means lucide's icon data ships as one object, not per-icon imports — there's no
tree-shaking per icon. It's small in absolute terms (path data only, not rendered markup), but if
that's ever a concern, a custom provider backed by
RegisterIconProvider and a glob path only includes the icons you actually reference.
Icon never throws. It logs a console warning and renders nothing both when no provider is
configured at all (IconProvider was never applied) and when name doesn't exist for the
resolved provider — a typo reaching you through untyped/dynamic code, for example.