🔄 SVG to React JSX Converter

Updated: 2026-07-11

Input SVG Code

SVG size: 0 chars

Options

Result (React JSX)

Waiting for conversion...

💡 How to Use

1. Paste SVG code into the input area
2. Configure options (TypeScript, size/color props)
3. Click "Convert to JSX" to convert
4. Automatic attribute conversion: class→className, stroke-width→strokeWidth, fill-rule→fillRule, etc.
5. Optional TypeScript React.FC type definitions

❓ FAQ

What attribute conversions does it handle?

The converter automatically transforms: class→className, stroke-width→strokeWidth, fill-rule→fillRule, clip-rule→clipRule, stroke-linecap→strokeLinecap, stroke-linejoin→strokeLinejoin, xmlns→removed, style→object notation, and all hyphenated SVG attributes to JSX camelCase format. Self-closing tags are also handled.

Why use size and color props?

Enabling "Support size prop" makes the component accept width/height parameters (default 24px). "Support color" passes stroke/fill colors via props. This makes your SVG icons reusable across your app — just drop the component and customize size/color via props without editing JSX.

How is TypeScript different?

When TypeScript is enabled, the generated component uses React.FC<React.SVGProps<SVGSVGElement>> type definitions with full type checking. The component is also automatically exported for use in .tsx files.

const SVG_ATTR_MAP = { 'class':'className','for':'htmlFor','tabindex':'tabIndex','autocomplete':'autoComplete','autofocus':'autoFocus','autoplay':'autoPlay','charset':'charSet','contenteditable':'contentEditable','crossorigin':'crossOrigin','datetime':'dateTime','enctype':'encType','formaction':'formAction','formenctype':'formEncType','formmethod':'formMethod','formnovalidate':'formNoValidate','formtarget':'formTarget','hrefLang':'hrefLang','httpEquiv':'httpEquiv','inputmode':'inputMode','ismap':'isMap','itemprop':'itemProp','itemscope':'itemScope','itemtype':'itemType','itemid':'itemID','itemref':'itemRef','maxlength':'maxLength','minlength':'minLength','nomodule':'noModule','novalidate':'noValidate','playsinline':'playsInline','readonly':'readOnly','referrerpolicy':'referrerPolicy','rowspan':'rowSpan','cellspacing':'cellSpacing','cellpadding':'cellPadding','colspan':'colSpan','usemap':'useMap','srcdoc':'srcDoc','srclang':'srcLang','srcset':'srcSet','viewbox':'viewBox' }; function toCamelCase(str){return str.replace(/-([a-z])/g,(_,c)=>c.toUpperCase());} function convertSvgToJsx(svg, opts){ const compName = opts.componentName||'SvgIcon'; const useTS = opts.useTypeScript; const sizeProps = opts.sizeProps; const colorProps = opts.colorProps; let result = svg.trim().replace(/<\?xml[^>]*\?>/g,'').replace(//g,'').replace(/]*>/gi,''); if(!result) return '// Paste SVG code first'; const svgMatch = result.match(/]*)>/i); if(!svgMatch) return '// No valid SVG tag found'; let svgAttrsStr = svgMatch[1]; let newAttrs = []; const attrRegex = /(\S+?)\s*=\s*"([^"]*)"|(\S+?)\s*=\s*'([^']*)'/g; let attrMatch; const usedAttrs = []; while((attrMatch = attrRegex.exec(svgAttrsStr)) !== null){ const name = attrMatch[1]||attrMatch[3]; const value = (attrMatch[2]||attrMatch[4]).replace(/"/g,'"'); const lower = name.toLowerCase(); if(lower==='xmlns'||lower.startsWith('xmlns:')||lower==='xml:space'||lower==='version') continue; let jsxAttr; if(lower in SVG_ATTR_MAP) jsxAttr = SVG_ATTR_MAP[lower]; else if(lower.includes('-')) jsxAttr = toCamelCase(lower); else jsxAttr = name; if(jsxAttr==='style'&&value.includes(':')){ newAttrs.push(`style={{${value.replace(/;\s*$/,'').split(';').map(s=>{ const parts=s.split(':');if(parts.length!==2)return s.trim(); return `${toCamelCase(parts[0].trim())}:'${parts[1].trim()}'`;}).join(',')}}`); continue; } newAttrs.push(`${jsxAttr}="${value}"`); usedAttrs.push(lower); } let reactProps = ''; if(sizeProps&&!usedAttrs.includes('width')&&!usedAttrs.includes('height')) reactProps=' width={size} height={size}'; if(colorProps&&!usedAttrs.includes('fill')&&!usedAttrs.includes('stroke')) reactProps+=' fill={color}'; else if(colorProps&&usedAttrs.includes('stroke')) reactProps+=' stroke={color}'; const svgOpenTag = ``; let innerContent = result.replace(/]*>/i,'').replace(/<\/svg>/i,'').trim(); innerContent = innerContent.replace(/<(\w+[^>]*)><\/(\w+)>/g,(m,attrs,tagName)=>{ if(tagName&&attrs.startsWith(tagName)) return `<${attrs}/>`; return m; }); let propsDef='',compProps='props',propDeclarations=''; if(sizeProps||colorProps){ const propLines=[]; if(sizeProps) propLines.push(' size: number = 24,'); if(colorProps) propLines.push(' color: string = "currentColor",'); propsDef=`interface ${compName}Props {\n${propLines.join('\n')}\n}`; compProps=useTS?`{ size = 24, color = "currentColor", ...props }: ${compName}Props`:`{ size = 24, color = "currentColor", ...props }`; } else compProps=useTS?'props: React.SVGProps':'props'; let output=''; if(useTS){ if(propsDef) output+=`${propsDef}\n\n`; output+=`const ${compName}: React.FC${sizeProps||colorProps?` & ${compName}Props`:''}> = (${compProps}) => (\n`; } else output+=`const ${compName} = (${compProps}) => (\n`; output+=` ${svgOpenTag}\n`; if(innerContent){ const indented=innerContent.split('\n').map(line=>line?` ${line}`:'').join('\n'); output+=indented+'\n'; } output+=` \n);\n\nexport default ${compName};`; return output; } const svgInput=document.getElementById('svgInput'); const jsxOutput=document.getElementById('jsxOutput'); document.getElementById('convertBtn').addEventListener('click',()=>{ const svg=svgInput.value; if(!svg.trim()){jsxOutput.textContent='// Paste SVG code first';return;} jsxOutput.textContent=convertSvgToJsx(svg,{componentName:document.getElementById('componentName').value||'SvgIcon',useTypeScript:document.getElementById('optTypeScript').checked,sizeProps:document.getElementById('optSizeProps').checked,colorProps:document.getElementById('optColorProps').checked}); }); document.getElementById('copyBtn').addEventListener('click',function(){ navigator.clipboard.writeText(jsxOutput.textContent).then(()=>showToast('JSX copied to clipboard ✓')).catch(()=>{const r=document.createRange();r.selectNode(jsxOutput);window.getSelection().removeAllRanges();window.getSelection().addRange(r);document.execCommand('copy');showToast('JSX copied to clipboard ✓');}); }); document.getElementById('exampleBtn').addEventListener('click',function(){ svgInput.value=`\n \n \n \n`; document.getElementById('inputSize').textContent=svgInput.value.length+' chars'; document.getElementById('convertBtn').click(); }); document.getElementById('clearBtn').addEventListener('click',function(){svgInput.value='';jsxOutput.textContent='Waiting for conversion...';document.getElementById('inputSize').textContent='0 chars';}); svgInput.addEventListener('input',function(){document.getElementById('inputSize').textContent=this.value.length+' chars';}); [document.getElementById('optTypeScript'),document.getElementById('optSizeProps'),document.getElementById('optColorProps'),document.getElementById('componentName')].forEach(el=>{el.addEventListener('change',()=>document.getElementById('convertBtn').click());}); document.getElementById('componentName').addEventListener('input',()=>document.getElementById('convertBtn').click()); function showToast(msg){const t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');setTimeout(()=>t.classList.remove('show'),2000);} // exampleBtn click handler already defined above