How to Convert Extracted Inline SVGs into Named React Components in icons.tsx
To convert extracted inline SVGs into named React components in src/components/icons.tsx, define a reusable IconProps type that extends React.SVGProps<SVGSVGElement>, wrap each raw SVG markup block in a named function component, and export them for type-safe use across your Next.js application.
When the AI website cloning pipeline in the JCodesMore/ai-website-cloner-template extracts raw <svg> markup from target sites, it stores the SVG code as plain text. To make these icons usable within the generated Next.js project, you must convert them into reusable, typed React components centralized in src/components/icons.tsx.
Why Convert Inline SVGs to React Components?
Raw SVG strings lack TypeScript safety and cannot accept dynamic Tailwind classes. By converting them to React components in src/components/icons.tsx, you enable className merging via the cn utility (as implemented in src/lib/utils.ts) and ensure consistent prop typing across the application, following the same pattern used in src/components/ui/button.tsx.
Step-by-Step Conversion Process
Step 1: Locate the Extracted SVG Markup
The cloning script saves each distinct <svg> block as plain text. Copy the raw markup including the opening <svg> tag and its attributes.
Step 2: Create the icons.tsx File
Create src/components/icons.tsx if it does not exist. This file serves as the single source of truth for all extracted icons in the repository.
Step 3: Define the IconProps Type
Define a reusable type that extends React's native SVG props:
import * as React from "react";
type IconProps = React.SVGProps<SVGSVGElement> & {
/** Optional className merged with the SVG's default classes */
className?: string;
};
Step 4: Wrap SVGs in Named Components
Convert each SVG into a named component that spreads props to the root element:
/** Search icon – extracted from the target site */
export const SearchIcon = (props: IconProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
className={props.className}
{...props}
>
<path d="M11 4a7 7 0 1 0 0 14..." />
</svg>
);
Repeat this pattern for every extracted SVG, choosing descriptive names like SearchIcon, ArrowRightIcon, or LogoIcon that reflect the visual function.
Step 5: Export and Consume the Icons
Export individual icons for tree-shaking and optionally a default map for dynamic imports:
export { SearchIcon, ArrowRightIcon, LogoIcon };
// Optional: Default export map for dynamic imports
const ICONS = {
Search: SearchIcon,
ArrowRight: ArrowRightIcon,
Logo: LogoIcon,
};
export default ICONS;
Complete icons.tsx Implementation Example
Here is the full skeleton for src/components/icons.tsx:
// src/components/icons.tsx
import * as React from "react";
type IconProps = React.SVGProps<SVGSVGElement> & {
className?: string;
};
/* SearchIcon – extracted from the target website */
export const SearchIcon = (props: IconProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
className={props.className}
{...props}
>
<path d="M11 4a7 7 0 1 0 0 14..." />
</svg>
);
/* ArrowRightIcon – navigation arrow extracted from the site */
export const ArrowRightIcon = (props: IconProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
className={props.className}
{...props}
>
<path d="M5 12h14M12 5l7 7-7 7" />
</svg>
);
/* LogoIcon – brand logo extracted from the site */
export const LogoIcon = (props: IconProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
fill="currentColor"
className={props.className}
{...props}
>
<circle cx="50" cy="50" r="40" />
</svg>
);
export { SearchIcon, ArrowRightIcon, LogoIcon };
Using Icons with the Button Component
Consume the icons in components like the Button:
import { SearchIcon } from "@/components/icons";
import { Button } from "@/components/ui/button";
<Button variant="default" size="default">
<SearchIcon className="mr-2 size-4" />
Search
</Button>
The className prop allows Tailwind sizing and coloring, consistent with the cn utility pattern found in src/lib/utils.ts.
Key Files and References
src/components/icons.tsx: Central location for all extracted SVG React components.src/lib/utils.ts: Contains thecnutility for className merging used throughout the template.src/components/ui/button.tsx: Demonstrates the pattern of accepting and mergingclassNameprops that icons should follow.
Summary
- Store all extracted SVG components in
src/components/icons.tsxfor centralized management. - Define an
IconPropstype that extendsReact.SVGProps<SVGSVGElement>to maintain type safety. - Spread props onto the
<svg>element to allow Tailwind class overrides via theclassNameprop. - Export icons individually for tree-shaking or as a default map for dynamic imports.
- Follow the same
classNamemerging pattern used insrc/components/ui/button.tsxfor consistency.
Frequently Asked Questions
How do I handle SVGs with existing class attributes?
Merge the existing classes with the className prop using the cn utility from src/lib/utils.ts, or simply pass props.className to the SVG's className attribute to allow Tailwind overrides while preserving default styling.
Can I use these icons with dynamic imports?
Yes. Export an ICONS map object as the default export from src/components/icons.tsx, then import it dynamically using import() or Next.js dynamic() imports to load icons on demand.
Should I remove the xmlns attribute from the SVG?
No. Keep the xmlns="http://www.w3.org/2000/svg" attribute on the root <svg> element to ensure proper rendering in all browsers, even when the component is used outside of standard HTML contexts.
How do I size the icons using Tailwind CSS?
Pass Tailwind utility classes like size-4, w-6, h-6, or text-red-500 via the className prop. The component spreads these props to the underlying <svg> element, allowing full styling control consistent with the cn utility pattern.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →