Building an Icon Library Tool: From Lucide React to Search Filtering
Building an Icon Library Tool: From Lucide React to Search Filtering#
Managing icons in frontend projects is always a hassle. Designers send a bunch of SVGs, developers manually import, name, and wrap them. Recently discovered Lucide React, a clean icon library with simple API and high-quality icons. Built an online icon library tool and documented the implementation approach.
Lucide React’s Design Philosophy#
Lucide is a community-maintained fork of Feather Icons with consistent style and clean lines. The key advantage is Tree-shaking support:
// ✅ Only import used icons, bundle grows on-demand
import { Home, Search, User } from 'lucide-react'
// ❌ Traditional icon library imports entire package
import * as Icons from '@iconify/react'
Each Lucide icon is an independent React component, implemented with SVG under the hood:
// lucide-react internal implementation
const Home = createLucideIcon('Home', [
['path', { d: 'm3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z' }],
['polyline', { points: '9 22 9 12 15 12 15 22' }]
])
createLucideIcon accepts an icon name and SVG path data, returning a React component. Path data is an array of SVG elements supporting path, circle, rect, etc.
Core Features of the Icon Library Tool#
1. Search Filtering Algorithm#
When users type keywords, filter the icon list in real-time. Key is supporting multiple matching methods:
const filteredIcons = useMemo(() => {
if (!search) return commonIcons
const term = search.toLowerCase()
return commonIcons.filter(icon =>
icon.name.toLowerCase().includes(term) ||
icon.keywords.toLowerCase().includes(term)
)
}, [search])
Using useMemo to cache filtered results, avoiding recalculation on every render. Search logic:
- Icon name matching:
Homematcheshome,homework - Keyword matching:
keywords: 'home, house, 首页'supports multilingual search
Keyword design is crucial. We preset common keywords for each icon:
const commonIcons = [
{ name: 'Home', keywords: 'home, house, 首页' },
{ name: 'Search', keywords: 'search, find, 搜索' },
{ name: 'User', keywords: 'user, person, 用户' },
// ...
]
2. Icon Size and Stroke Control#
Lucide React supports two key props: size and strokeWidth:
<Home size={24} strokeWidth={2} />
size controls icon dimensions, strokeWidth controls line thickness. Tool implementation:
const [size, setSize] = useState(24)
const [strokeWidth, setStrokeWidth] = useState(2)
// Slider control
<input
type="range"
min={16}
max={48}
value={size}
onChange={(e) => setSize(parseInt(e.target.value))}
/>
strokeWidth range is set to 1-3 with 0.5 steps. Thinner strokes blur on Retina screens, thicker strokes lose detail.
3. One-Click Copy Functionality#
Click an icon to copy import code and component code:
const handleCopy = async (iconName: string) => {
const importCode = `import { ${iconName} } from 'lucide-react'`
const svgCode = `<${iconName} size={${size}} strokeWidth={${strokeWidth}} />`
await navigator.clipboard.writeText(`${importCode}\n${svgCode}`)
// Copy success feedback
setCopied(iconName)
setTimeout(() => setCopied(null), 2000)
}
navigator.clipboard.writeText() is a modern browser API for copying text to clipboard. After successful copy, the icon changes to a checkmark, reverting after 2 seconds.
Performance Optimization Details#
1. useMemo Caching Filter Results#
With 50+ icons, recalculating filtering on every input has performance overhead:
const filteredIcons = useMemo(() => {
// ...filtering logic
}, [search]) // Only recalculate when search changes
2. Dynamic Rendering Optimization#
Icon grid uses CSS Grid layout, browsers automatically optimize repaints:
<div className="grid grid-cols-6 sm:grid-cols-8 md:grid-cols-10 lg:grid-cols-12 gap-3">
{filteredIcons.map(icon => (
<button key={icon.name} onClick={() => handleCopy(icon.name)}>
{/* Icon content */}
</button>
))}
</div>
Responsive column design:
- Small screen: 6 columns
- Medium screen: 8 columns
- Large screen: 10 columns
- Extra large screen: 12 columns
3. Search Debouncing (Optional Optimization)#
With hundreds of icons, add debouncing:
const [debouncedSearch, setDebouncedSearch] = useState('')
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedSearch(search)
}, 300) // 300ms debounce
return () => clearTimeout(timer)
}, [search])
const filteredIcons = useMemo(() => {
if (!debouncedSearch) return commonIcons
// ...filtering logic
}, [debouncedSearch])
Edge Cases#
1. Icon Name Conflicts#
If your project already has a Home component, import conflicts:
// ❌ Conflict
import { Home } from 'lucide-react'
import Home from './components/Home'
// ✅ Rename
import { Home as HomeIcon } from 'lucide-react'
Consider adding alias options in generated code.
2. Icon Not Found#
Show a prompt when search has no results:
{filteredIcons.length === 0 && (
<div className="text-center py-12 text-text-secondary">
No matching icons found
</div>
)}
3. Icon Loading Failure#
Lucide React supports on-demand icon loading, throwing errors for non-existent icons. Wrap with try-catch:
import * as LucideIcons from 'lucide-react'
const iconName = 'NonExistentIcon'
const IconComponent = LucideIcons[iconName]
if (!IconComponent) {
console.warn(`Icon ${iconName} does not exist`)
return <FallbackIcon />
}
Real-World Use Cases#
1. Rapid Prototyping#
During prototype development, copy code directly from the icon library to quickly build interfaces:
import { Home, Search, User, Settings } from 'lucide-react'
function Navigation() {
return (
<nav>
<Home /> <Search /> <User /> <Settings />
</nav>
)
}
2. Unified Icon Management#
In team development, use Lucide icon library uniformly to avoid inconsistent styles from designer-provided SVGs.
3. Design System Integration#
Lucide’s clean, consistent icon style is perfect as a design system’s base icon set.
Final Result#
Based on the above approach, built an online tool: Icon Library
Key features:
- 50+ common icons
- Real-time search filtering
- Adjustable size and stroke
- One-click copy import code
Lucide React itself is already excellent. The tool just simplifies icon discovery and copying. Hope this helps.
Related tools: Button Generator | Color Extractor