Skip to content

Instantly share code, notes, and snippets.

@deckchairlabs
Created December 4, 2022 09:06
Show Gist options
  • Save deckchairlabs/7990a37e9157bbbc8e4d385150ef3366 to your computer and use it in GitHub Desktop.
Save deckchairlabs/7990a37e9157bbbc8e4d385150ef3366 to your computer and use it in GitHub Desktop.
Generate an icons.svg and Icon.tsx component from your icon components!
import { CheckIcon, Cross2Icon, ChevronDownIcon, ChevronUpIcon } from "@radix-ui/react-icons";
import { createElement } from "react";
import { renderToString } from "react-dom/server";
import { dirname, join } from "path";
import { fileURLToPath } from "url";
import { writeFile } from "fs/promises";
import { format } from "prettier";
const __dirname = dirname(fileURLToPath(import.meta.url));
const icons = {
check: CheckIcon,
cross2: Cross2Icon,
chevronDown: ChevronDownIcon,
chevronUp: ChevronUpIcon,
};
const sprites = [];
for (const icon of Object.entries(icons)) {
const sprite = renderToString(createElement(icon[1], { id: icon[0], xmlns: undefined }))
.replace("<svg", "<symbol")
.replace("</svg>", "</symbol>");
sprites.push(sprite);
}
const IconComponent = format(
`
import React from "react";
type Icons = ${Object.keys(icons)
.map((icon) => `"${icon}"`)
.join(" | ")};
type IconProps = React.SVGAttributes<SVGElement> & {
id: Icons;
children?: never;
};
export default function Icon({ id, ...props }: IconProps) {
return (
<svg {...props}>
<use href={\`/icons.svg#\${id\}\`} />
</svg>
)
}
`,
{ parser: "typescript" }
);
const spriteSheet = format(
`
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
${sprites.join("\n")}
</defs>
</svg>`,
{
parser: "html",
}
);
const appDir = join(__dirname, "../apps/web");
await writeFile(join(appDir, "public/icons.svg"), spriteSheet);
await writeFile(join(appDir, "components/Icon.tsx"), IconComponent);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment