Custom Icon System¶
Navigation: Home → Features & Components → Custom Icons
Table of Contents¶
- Introduction
- Icon Components
- Implementation Details
- Usage Examples
- Creating Custom Icons
- Best Practices
- See Also
- Next Steps
Introduction¶
The Custom Icon System provides SVG icon components for social media platforms and common actions. These custom icons complement Lucide React icons and maintain consistent styling across the application.
Available Icons¶
- GitHubIcon: GitHub logo
- LinkedInIcon: LinkedIn logo
- FileDownloadIcon: Download/resume icon
Why Custom Icons?¶
- Brand Accuracy: Official logo SVGs match brand guidelines
- Performance: Inline SVGs load faster than images
- Styling Control: Can be styled with CSS/Tailwind
- Accessibility: Proper alt text and ARIA attributes
- Tree-Shaking: Only used icons are included in bundle
Icon Components¶
Export Index¶
```typescript:1:3:components/icons/index.ts export { GitHubIcon } from "./github-icon"; export { LinkedInIcon } from "./linkedin-icon"; export { FileDownloadIcon } from "./file-download-icon";
Centralized exports allow clean imports:
```typescript
import { GitHubIcon, LinkedInIcon } from "@/components/icons";
Implementation Details¶
GitHubIcon Component¶
```typescript:1:22:components/icons/github-icon.tsx import { SVGProps } from "react"; import { cn } from "@/lib/utils";
export function GitHubIcon({ className, ...props }: SVGProps
export default GitHubIcon;
### Icon Pattern
All custom icon components follow this pattern:
```typescript
import { SVGProps } from "react";
import { cn } from "@/lib/utils";
export function IconName({ className, ...props }: SVGProps<SVGSVGElement>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="..." // Original viewBox
className={cn("size-full", className)} // Default + custom classes
{...props} // Spread remaining SVG props
>
{/* SVG path data */}
</svg>
);
}
export default IconName;
Key Features¶
- TypeScript Props: Accepts all standard SVG props
- className Merging: Uses
cn()to merge classes - Default Sizing:
size-fullmakes icon fill parent - currentColor:
fill="currentColor"inherits text color - Accessible: Can add
aria-labelandrolevia props
Usage Examples¶
Basic Icon¶
With Custom Color¶
The icon uses fill="currentColor", so text-* classes control the color.
In Social Link¶
import { GitHubIcon } from "@/components/icons";
import SocialLink from "@/components/social-link";
<SocialLink
href="https://github.com/username"
ariaLabel="GitHub Profile"
icon={GitHubIcon}
/>
Hover Effects¶
Responsive Sizing¶
With ARIA Label¶
Inline with Text¶
<a href="https://github.com/username" className="flex items-center gap-2">
<GitHubIcon className="h-5 w-5" />
<span>View on GitHub</span>
</a>
Creating Custom Icons¶
Step 1: Obtain SVG¶
Get official brand SVG from:
- Simple Icons - Brand logos
- SVG Repo - Open source SVGs
- Official brand press kits
Step 2: Create Component File¶
// components/icons/twitter-icon.tsx
import { SVGProps } from "react";
import { cn } from "@/lib/utils";
export function TwitterIcon({ className, ...props }: SVGProps<SVGSVGElement>) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
className={cn("size-full", className)}
{...props}
>
<path
fill="currentColor"
d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"
/>
</svg>
);
}
export default TwitterIcon;
Step 3: Update Index¶
// components/icons/index.ts
export { GitHubIcon } from "./github-icon";
export { LinkedInIcon } from "./linkedin-icon";
export { FileDownloadIcon } from "./file-download-icon";
export { TwitterIcon } from "./twitter-icon"; // Add new icon
Step 4: Use Icon¶
Best Practices¶
Sizing¶
// ✅ Good - Use Tailwind size classes
<GitHubIcon className="h-6 w-6" />
<GitHubIcon className="size-8" />
// ❌ Avoid - Inline styles
<GitHubIcon style={{ width: '24px', height: '24px' }} />
Coloring¶
// ✅ Good - Use text color (works with currentColor)
<GitHubIcon className="text-primary" />
<GitHubIcon className="text-blue-500 hover:text-blue-600" />
// ❌ Avoid - fill attribute (overrides currentColor)
<GitHubIcon fill="#3b82f6" />
Accessibility¶
// ✅ Good - Decorative icon (in link with text)
<a href="...">
<GitHubIcon className="h-5 w-5" aria-hidden="true" />
<span>GitHub</span>
</a>
// ✅ Good - Standalone icon (needs label)
<button>
<GitHubIcon className="h-5 w-5" aria-label="GitHub" role="img" />
</button>
// ❌ Avoid - No context
<GitHubIcon className="h-5 w-5" />
Performance¶
// ✅ Good - Import only needed icons
import { GitHubIcon, LinkedInIcon } from "@/components/icons";
// ❌ Avoid - Import entire index (larger bundle)
import * as Icons from "@/components/icons";
Naming¶
// ✅ Good - Descriptive, suffixed with "Icon"
GitHubIcon;
LinkedInIcon;
TwitterIcon;
// ❌ Avoid - Vague names
GitHub;
Logo;
Social;
See Also¶
- Lucide React - Icon library for general icons
- Simple Icons - Brand SVG source
- Social Link Component - Usage with social links
- SVG Optimization - SVGO web tool
Next Steps¶
- Icon Library Expansion: Add more social platform icons
- Animated Icons: Add hover animations with CSS/GSAP
- Icon Sprite Sheet: Combine into SVG sprite for better caching
- Icon Generator: Script to automate icon component creation
- Duotone Icons: Support two-color icons
- Icon Documentation: Create visual icon catalog page
Last Updated: 2024-02-09
Related Docs: Components | Social Utilities | Footer