SvgFinder.tsx
A utility component for rendering Lucide or custom SVG icons dynamically by name.
The SvgFinder component dynamically renders SVG icons by name, supporting both Lucide icons and custom icons. It's ideal for rendering icons from user input, locale files, or dynamic data.
SVG Component Requirements
Custom icons must be React components that accept size and className props. Use fill="currentColor" and stroke="currentColor" in your SVG paths to enable Tailwind color classes like text-blue-400 to work properly.
Props
| SvgFinder Props | Type | Default |
|---|---|---|
icon | string | - |
size? | number | 18 |
className? | string | - |
Usage
Lucide Icons
Render any icon from the Lucide icon library:
import { SvgFinder } from '@/components/svgs/SvgFinder';
export function Example() {
return (
<div className="flex gap-2">
<SvgFinder icon="Check" size={24} className="text-green-500" />
<SvgFinder icon="X" size={24} className="text-red-500" />
<SvgFinder icon="Star" size={24} className="text-yellow-500" />
</div>
);
}Custom Icons
Render custom icons registered in CustomIcons.ts:
import { SvgFinder } from '@/components/svgs/SvgFinder';
export function Example() {
return (
<div className="flex gap-2">
<SvgFinder icon="GitHub" size={24} className="text-foreground" />
<SvgFinder icon="Google" size={24} className="text-foreground" />
<SvgFinder icon="CBuild" size={20} className="text-primary" />
</div>
);
}Dynamic Icons from Data
Render icons dynamically from arrays or objects:
import { SvgFinder } from '@/components/svgs/SvgFinder';
const technologies = [
{ name: 'Next.js', icon: 'Zap' },
{ name: 'TypeScript', icon: 'Code' },
{ name: 'Tailwind', icon: 'Palette' },
];
export function TechStack() {
return (
<div className="flex gap-4">
{technologies.map((tech) => (
<div key={tech.name} className="flex items-center gap-2">
<SvgFinder icon={tech.icon} size={20} />
<span>{tech.name}</span>
</div>
))}
</div>
);
}From Locale Files
Render icons configured in locale files:
import { SvgFinder } from '@/components/svgs/SvgFinder';
import locale from '@/locales/en.json';
export function Navigation() {
const navItems = locale?.navigation?.buttons;
return (
<nav className="flex gap-4">
{navItems?.map((item) => (
<a key={item.id} href={item.href} className="flex items-center gap-2">
{item.icon && <SvgFinder icon={item.icon} size={18} />}
<span>{item.name}</span>
</a>
))}
</nav>
);
}Features
- Dual Source Support: Renders both Lucide and custom icons
- Fallback Handling: Returns
nullif icon not found - Dynamic Rendering: Uses React
createElementfor runtime icon selection - Type Safety: TypeScript support with icon name validation
- Flexible Styling: Accepts Tailwind classes for customization
- Consistent API: Same props for all icon types
Implementation Details
Icon Resolution Order
The component searches for icons in this order:
- Lucide Icons: Checks if icon exists in Lucide library
- Custom Icons: Checks if icon exists in
CustomIconsregistry - Fallback: Returns
nullif not found
// 1. Check Lucide icons
if (icons[icon as keyof typeof icons]) {
return createElement(icons[icon as keyof typeof icons], {
size: size,
className: className,
});
}
// 2. Check custom icons
if (!CustomIcons[icon as keyof typeof icons]) {
return null;
}
return createElement(CustomIcons[icon as keyof typeof icons], {
size: size,
className: className,
});Dynamic Rendering
The component uses React's createElement to dynamically render icons:
import { createElement } from 'react';
createElement(IconComponent, {
size: size,
className: className,
});This allows icon selection at runtime without importing all icons.
Customization
Icon Size
<SvgFinder icon="Star" size={16} /> {/* Small */}
<SvgFinder icon="Star" size={24} /> {/* Medium */}
<SvgFinder icon="Star" size={32} /> {/* Large */}Icon Colors
Use Tailwind color classes (requires fill="currentColor" in SVG):
<SvgFinder icon="Check" className="text-green-500" />
<SvgFinder icon="Star" className="fill-yellow-400 stroke-yellow-400" />Common Use Cases
Navigation Icons
<nav>
<a href="/home">
<SvgFinder icon="Home" size={20} />
Home
</a>
</nav>Status Indicators
const iconMap = {
success: 'CheckCircle',
error: 'XCircle',
warning: 'AlertTriangle',
};
<SvgFinder icon={iconMap[status]} size={16} />Social Media Links
const socials = [
{ name: 'GitHub', icon: 'GitHub', url: 'https://github.com' },
{ name: 'Twitter', icon: 'Twitter', url: 'https://twitter.com' },
];
{socials.map((social) => (
<a key={social.name} href={social.url}>
<SvgFinder icon={social.icon} size={24} />
</a>
))}Error Handling
The component returns null if the icon doesn't exist (no error thrown).
Related
- CustomIcons.ts - Custom icon registry
- Lucide Icons - Icon library documentation
- Adding Custom Icons - Recipe for adding icons
How is this guide ?
Last updated on