I have a page of iconCard components that consume icon components. I have added a button to each card to allow downloading the icon for each card on click of a button contained on that card with the 'downloadSVG' function. I see the download happen, and the images are named appropriately (svgFile.svg) and saved into my Downloads folder, but when I open my downloads folder on my machine and click on the svg file, I get this error:
Namespace prefix xlink for href on use is not defined
I have read about the deprecated xlink namespace for href attributes, but when I remove 'xlink' and just use 'href' it doesn't resolve the issue. The path to my icons is as follows:
project/public/assets/icons/[icon-name]/[icon-name.svg]
Here is my code.
import React, { useCallback, useRef } from 'react';
import PropTypes from 'prop-types';
import { CbdsButton, CbdsIcon } from '@cbds/cbds-components-react';
import ButtonInlineCode from '../ButtonInlineCode';
const IconCard = ({ iconName, size, color, library, a11yRole, a11yLabel }) => {
const svgRef = useRef();
const downloadSVG = useCallback(() => {
const svg = svgRef.current.innerHTML;
const blob = new Blob([svg], { type: "image/svg+xml" });
downloadBlob(blob, `${iconName}.svg`);
}, []);
return (
<div className="cbdsws-c-iconCard">
<div className="cbdsws-c-iconCard__media" ref={svgRef}>
<CbdsIcon iconName={iconName} size={size} color={color} library={library} a11yRole={a11yRole} a11yLabel={a11yLabel ? a11yLabel : iconName} />
</div>
<div className="cbdsws-c-iconCard__body">
<div className="cbdsws-c-iconCard__copyBtn cbdsws-c-iconCard__longName">
<ButtonInlineCode codeSnippet={iconName} type={library === "ui" ? "icon" : "iconBrand"} />
<br />
<CbdsButton size="sm" onClick={downloadSVG} variant="ghost" label="Download" />
</div>
</div>
</div>
);
function downloadBlob(blob, filename) {
const objectUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = objectUrl
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
setTimeout(() => URL.revokeObjectURL(objectUrl), 5000);
}
};
IconCard.propTypes = {
iconName: PropTypes.string.isRequired,
size: PropTypes.oneOf([
"sm",
"md",
"12",
"16",
"20",
"24",
"28",
"60",
"80",
"120",
]),
color: PropTypes.oneOf(["primary", "light", "dark"]),
library: PropTypes.oneOf(["ui", "brand"]),
a11yRole: PropTypes.string,
a11yLabel: PropTypes.string,
};
IconCard.defaultProps = {
iconName: "close",
size: null,
color: null,
library: "ui",
a11yRole: "img",
};
export default IconCard;
And here is an example of one of the SVG files. They're all like this one. I suppose it's possible I may need to add Namespacing to each svg. There are hundreds of them. The ones on the cards are being pulled from 2 sprites, but to download them, I had to save each individual one to a folder.
<svg width="48" height="48" viewBox="0 0 48 48">
<path fill-rule="evenodd" d="M24 4c10.985 0 20 9.015 20 20s-9.015 20-20 20S4 34.985 4 24 13.015 4 24 4zm0 10c-1.003 0-2 1-2 2v6h-6c-.999 0-2 1-2 2s1 2 2 2h6v6c0 1 1 2 2 2s2-1 2-2v-6h6c1 0 2-1 2-2s-1-2-2-2h-6v-6c0-1.001-.997-2-2-2z"></path>
</svg>
Can anyone please shed some light? Thank you.