Skip to main content
MorpheusIcons
Bring Your Own Icons — icondata, Lucide, Heroicons, Tabler & Phosphor

Using Lucide via Cargo, npm or lucide.dev in Any Project

MorpheusIcons works with any icon library from Cargo crates, npm, or lucide.dev. Start with the Rust crate icondata, or load SVGs from npm packages like lucide-static and fetch them from a CDN.

1. Using Lucide in Rust via Cargo (icondata)

Using the icondata Rust crate or lucide.dev site SVGs

A Option A: Using the icondata Crate (Lucide, Heroicons, Tabler for Rust)

In Rust, the popular icondata crate packages Lucide, Heroicons, Tabler, and Phosphor icons into Rust constants:

# Cargo.toml
[dependencies]
icondata = "0.4"
morpheusicons = "0.1"

Pass icondata path data directly into MorpheusIcons:

use icondata::{LuSun, LuMoon}; // Lucide icons from icondata crate
use morpheusicons::prelude::*;

fn main() {
    // icondata provides SVG path string in .data field
    let sun_path  = LuSun.data;
    let moon_path = LuMoon.data;

    let mut controller = MorphController::from_sources(
        &sun_path,
        &moon_path,
        SpringConfig::BOUNCY,
    ).unwrap();

    controller.set_target(1.0); // Morph to Moon!
    controller.update(0.016);
}

B Option B: Copying Directly from lucide.dev

  1. Open lucide.dev/icons
  2. Search for any icon (for example play, pause, sun)
  3. Click Copy SVG, or save the .svg file into your project
  4. Pass it through icon_from_svg to convert the full SVG
use morpheusicons::icons::svg_extract::icon_from_svg;
use morpheusicons::prelude::*;

// Load the .svg files saved straight from lucide.dev
let play_svg  = icon_from_svg(include_str!("../assets/lucide/play.svg")).unwrap();
let pause_svg = icon_from_svg(include_str!("../assets/lucide/pause.svg")).unwrap();

let mut controller = MorphController::from_sources(&play_svg, &pause_svg, SpringConfig::SNAPPY).unwrap();

2. Using Lucide from npm in JavaScript / Web Apps

Integrating lucide-static or Lucide CDN with MorpheusIcons WebAssembly

A Option A: Using the lucide-static npm Package

Install the official lucide-static package in your web project (Vite, Next.js, Webpack, etc.):

npm install lucide-static

Then import Lucide icon paths and feed them directly into MorpheusIcons:

import init, { WasmMorphController } from './pkg/morpheusicons.js';

// Import raw SVG strings from lucide-static in Vite/Webpack
import sunSvg from 'lucide-static/icons/sun.svg?raw';
import moonSvg from 'lucide-static/icons/moon.svg?raw';

await init();

// Extract path d="..." string or pass path directly
const sunPath  = "M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8z";
const moonPath = "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9z";

// Create WASM controller (startPath, targetPath, springPreset)
const controller = new WasmMorphController(sunPath, moonPath, "bouncy");

// Trigger morph animation to Moon (t=1.0)
controller.morphToEnd();

// Animation frame loop (60fps)
function animate(dtSeconds) {
  const isAnimating = controller.update(dtSeconds);
  
  // Set calculated continuous SVG path
  document.getElementById('icon-path').setAttribute('d', controller.currentSvgPath());

  if (isAnimating) requestAnimationFrame(animate);
}

B Option B: Fetching Lucide Icons Dynamically from CDN (unpkg / jsDelivr)

No build tools required! You can fetch any icon dynamically from Lucide's CDN:

// Fetch raw SVG files for any Lucide icon directly from unpkg CDN
const [sunSvg, moonSvg] = await Promise.all([
  fetch('https://unpkg.com/lucide-static@latest/icons/sun.svg').then(r => r.text()),
  fetch('https://unpkg.com/lucide-static@latest/icons/moon.svg').then(r => r.text())
]);

// Extract d="..." attribute using simple regex
const extractD = (svg) => svg.match(/d="([^"]+)"/)?.[1] || "";

const controller = new WasmMorphController(
  extractD(sunSvg),
  extractD(moonSvg),
  "gentle"
);
3

GUI Framework Integration Examples

Ready-to-copy code snippets for GPUI, egui, Iced, Leptos, Dioxus & WASM

GPUI (Zed Editor Framework)

feature = "gpui"
use gpui::*;
use morpheusicons::integrations::gpui::MorphIcon;
use morpheusicons::prelude::*;

struct AppView {
    morph_ctrl: MorphController,
}

impl Render for AppView {
    fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
        div()
            .flex()
            .items_center()
            .justify_center()
            .child(
                MorphIcon::new(&self.morph_ctrl)
                    .size(px(32.0))
                    .stroke_color(rgb(0x16a34a))
                    .stroke_width(2.0)
            )
    }
}

egui Immediate-Mode UI

feature = "egui"
use egui::Ui;
use morpheusicons::integrations::egui::show_morph_icon;
use morpheusicons::prelude::*;

fn draw_icon(ui: &mut Ui, ctrl: &MorphController) {
    show_morph_icon(ui, ctrl, 36.0, egui::Color32::from_rgb(22, 163, 74));
}

Leptos Reactive Web Components

feature = "leptos"
use leptos::*;
use morpheusicons::integrations::leptos::MorpheusIcon;
use morpheusicons::prelude::*;

#[component]
pub fn PlayPauseButton() -> impl IntoView {
    let (progress, set_progress) = create_signal(0.0);

    view! {
        <button on:click=move |_| set_progress.update(|p| *p = 1.0 - *p)>
            <MorpheusIcon
                source=Icon::Play
                target=Icon::Pause
                progress=progress
                config=SpringConfig::BOUNCY
                size=32.0
            />
        </button>
    }
}