In the standard lucide package, icons are exported as JSON arrays with the following contents:
: "svg" : element attributes : children
We need to import these JSON files and render their data as HTML.
Render a single icon
To render a single Lucide icon:
Import any lucide icon
Destructure attributes and children array items from that icon
Reduce children nodes to HTML string
Render an <svg> component
Spread attributes directly on the element
Apply childElements with the set:html directive
Extract LucideIcon component
Now that we can render icons, let’s extract this code as a reusable component.
Move the relevant code to src/components/lucide-icon.astro
Refactor to icon as a prop
Take rest ...props so HTML and SVG attributes can be applied at the call site
Merge icon attributes and component props
Apply munged attributes-props to exported svg element
Use the LucideIcon component
To use our new LucideIcon component, import it along with any lucide icon.
Provide the icon JSON to LucideIcon using the icon prop.
Apply attributes to LucideIcon
The LucideIcon receives props that it merges with the default lucide values.
Use these to change SVG attributes like height, width, fill, and stroke-width.
Or apply common attributes like class and id.
Taking it further
My preference is to keep icon importing and SVG rendering separated.
But you may find this cumbersome.
If so, create a facade for LucideIcon that exposes your favorite icons via string interface.
This could look something like this:
Go further with TypeScript
lucide does not expose its IconNode type for external use.
So, if you want to use my code above in TypeScript, you’ll need to get clever.
Import just the type of any component.
Infer the IconNode for that icon in the LucideIcon type declaration.
Add any optional svg attributes you’d like to support.
(e.g., height, width, fill, stroke-width, etc.)
I hope that you found this useful in building an Astro site.
If you’d like to see more Astro tips and tricks, bug me on Twitter/X or Discord. 😄