ikonik
v1.0.0
Published
SVG to React icon generator - tree-shakeable, accessible, customizable
Maintainers
Readme
Ikonik
Transform your SVG files into tree-shakeable, accessible React components with ease.
Features
- Tree-shakeable - Import only the icons you need
- Accessible - Built-in ARIA support and semantic HTML
- Customizable - Control size, stroke width, and colors
- Optimized - Automatic SVG optimization with SVGO
- TypeScript - Full type safety out of the box
- Zero Config - Works out of the box with sensible defaults
Installation
Add to your project as a dev dependency:
npm install -D ikonikQuick Start
1. Prepare your SVG files:
my-project/
├── icons-src/
│ ├── arrow-left.svg
│ ├── arrow-right.svg
│ └── home.svg
└── package.json2. Add a script to your package.json:
{
"scripts": {
"icons": "ikonik --src ./icons-src --out ./src/components/icons"
}
}3. Generate React components:
npm run icons4. Use in your React app:
import { ArrowLeft, ArrowRight, Home } from './components/icons';
function App() {
return (
<div>
<Home size={32} />
<ArrowLeft strokeWidth={2} />
<ArrowRight className="text-blue-500" />
</div>
);
}Usage
ikonik [options]Options
| Option | Description | Default |
|--------|-------------|---------|
| -s, --src <dir> | Source SVG directory | icons-src |
| -o, --out <dir> | Output directory | icons |
| --prefix <name> | Component name prefix | "" |
| --size <num> | Default size in pixels | 24 |
| --stroke <num> | Default stroke width | 1.5 |
| --fill | Treat icons as filled (no stroke) | false |
Examples
In package.json scripts:
{
"scripts": {
"icons": "ikonik",
"icons:outline": "ikonik --src ./outline --out ./src/icons/outline",
"icons:solid": "ikonik --src ./solid --out ./src/icons/solid --fill",
"icons:branded": "ikonik --src ./brands --out ./src/icons/brands --prefix Brand"
}
}Direct usage:
# Basic
npx ikonik
# Custom directories
npx ikonik --src ./svg-files --out ./src/icons
# With prefix
npx ikonik --prefix Icon
# Filled icons
npx ikonik --fill --stroke 0
# Custom defaults
npx ikonik --size 20 --stroke 2Component API
Each generated component accepts these props:
interface IconProps extends React.SVGProps<SVGSVGElement> {
title?: string; // Accessible title
titleId?: string; // Custom title ID
size?: number; // Icon size (width & height)
strokeWidth?: number; // Stroke width (outline icons)
className?: string; // CSS classes
// ... all other SVG props
}Component Examples
// Custom size
<Home size={48} />
// Custom stroke width
<ArrowLeft strokeWidth={3} />
// With title for accessibility
<Home title="Go to homepage" />
// With Tailwind CSS
<ArrowRight className="text-blue-500 hover:text-blue-700" />
// With inline styles
<Home style={{ color: '#FF0000' }} />
// Forward ref
const iconRef = useRef<SVGSVGElement>(null);
<Home ref={iconRef} />Output Structure
icons/
├── ArrowLeft.tsx
├── ArrowRight.tsx
├── Home.tsx
├── index.ts # Barrel export
└── metadata.json # Icon metadataWorkflow Integration
Watch Mode
Add a watch script to regenerate icons when SVGs change:
{
"scripts": {
"icons": "ikonik --src ./icons-src --out ./src/icons",
"icons:watch": "chokidar 'icons-src/**/*.svg' -c 'npm run icons'"
},
"devDependencies": {
"chokidar-cli": "^3.0.0",
"ikonik": "^1.0.0"
}
}Pre-commit Hook
Ensure icons are always up to date:
{
"husky": {
"hooks": {
"pre-commit": "npm run icons && git add src/icons"
}
}
}CI/CD
Check if icons are up to date in CI:
# .github/workflows/ci.yml
- name: Check icons are up to date
run: |
npm run icons
git diff --exit-code src/icons/ || (echo "Icons are out of date. Run 'npm run icons'" && exit 1)Framework Integration
Next.js
// app/page.tsx
import { Home, ArrowLeft } from '@/components/icons';
export default function Page() {
return <Home size={32} />;
}Vite
// src/App.tsx
import { Home } from './icons';
export default function App() {
return <Home size={32} />;
}Remix
// app/routes/_index.tsx
import { Home } from '~/components/icons';
export default function Index() {
return <Home size={32} />;
}Styling
Icons inherit the current text color by default:
// Using CSS
<div style={{ color: 'blue' }}>
<Home /> {/* Will be blue */}
</div>
// Using Tailwind
<div className="text-red-500">
<Home /> {/* Will be red */}
</div>
// Using CSS Modules
<div className={styles.iconContainer}>
<Home />
</div>Metadata
Ikonik generates a metadata.json file with information about all icons:
{
"count": 3,
"icons": [
{
"name": "ArrowLeft",
"file": "ArrowLeft",
"tags": ["arrow", "left"]
}
]
}Use this for building icon pickers, documentation, or search functionality.
Different Icon Styles
Generate multiple sets of icons with different styles:
{
"scripts": {
"icons:outline": "ikonik --src ./icons/outline --out ./src/icons/outline --stroke 2",
"icons:solid": "ikonik --src ./icons/solid --out ./src/icons/solid --fill",
"icons:mini": "ikonik --src ./icons/mini --out ./src/icons/mini --size 20 --fill",
"icons:all": "npm run icons:outline && npm run icons:solid && npm run icons:mini"
}
}Then import from different sets:
import { Home } from './icons/outline';
import { Home as HomeSolid } from './icons/solid';
import { Home as HomeMini } from './icons/mini';Why Local Installation?
Modern best practices favor local installations because:
- Version control - Each project can use different versions
- Reproducibility - package.json locks the version for all team members
- No conflicts - Multiple projects can use different versions simultaneously
- Better CI/CD - Works seamlessly in automated environments
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT
