We use tracking cookies to understand how you use the product and help us improve it. For more information on how we store cookies, read our  privacy policy.

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 PropsTypeDefault
icon
string
-
size?
number
18
className?
string
-

Usage

Lucide Icons

Render any icon from the Lucide icon library:

@/components/Example.tsx
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:

@/components/Example.tsx
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:

@/components/TechStack.tsx
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:

@/components/Navigation.tsx
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 null if icon not found
  • Dynamic Rendering: Uses React createElement for 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:

  1. Lucide Icons: Checks if icon exists in Lucide library
  2. Custom Icons: Checks if icon exists in CustomIcons registry
  3. Fallback: Returns null if not found
Resolution Logic
// 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:

Dynamic Creation
import { createElement } from 'react';

createElement(IconComponent, {
  size: size,
  className: className,
});

This allows icon selection at runtime without importing all icons.

Customization

Icon Size

Different Sizes
<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):

Colored Icons
<SvgFinder icon="Check" className="text-green-500" />
<SvgFinder icon="Star" className="fill-yellow-400 stroke-yellow-400" />

Common Use Cases

@/components/Navigation.tsx
<nav>
  <a href="/home">
    <SvgFinder icon="Home" size={20} />
    Home
  </a>
</nav>

Status Indicators

@/components/StatusBadge.tsx
const iconMap = {
  success: 'CheckCircle',
  error: 'XCircle',
  warning: 'AlertTriangle',
};

<SvgFinder icon={iconMap[status]} size={16} />
@/components/SocialLinks.tsx
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).

How is this guide ?

Last updated on