diff --git a/packages/ui/src/components/icon/Icon.tsx b/packages/ui/src/components/icon/Icon.tsx index 3956cfba..be6077de 100644 --- a/packages/ui/src/components/icon/Icon.tsx +++ b/packages/ui/src/components/icon/Icon.tsx @@ -30,6 +30,29 @@ function ensureSpriteOnce() { spriteInjected = true } +/** + * Append a single missing symbol. Needed when the sprite was injected before a + * newly generated icon landed (HMR / late sprite regenerate) — a one-shot inject + * would otherwise leave `` pointing at nothing. + */ +function ensureSpriteSymbol(name: IconName) { + if (typeof document === "undefined") return + ensureSpriteOnce() + if (document.getElementById(`oc-${name}`)) return + + const content = iconSpriteData[name] + if (typeof content !== "string") return + + const sprite = document.getElementById(SPRITE_ID) + if (!sprite) return + + const symbol = document.createElementNS("http://www.w3.org/2000/svg", "symbol") + symbol.id = `oc-${name}` + symbol.setAttribute("viewBox", "0 0 24 24") + symbol.innerHTML = content + sprite.appendChild(symbol) +} + export interface IconProps extends React.ComponentPropsWithoutRef<"svg"> { name: IconName } @@ -38,7 +61,7 @@ export const Icon = React.memo(({ name, className, ...rest }: IconProps) => { // Inline sprite injection during render – must run before tries // to resolve the #oc-* reference during the same commit. if (typeof document !== "undefined") { - ensureSpriteOnce() + ensureSpriteSymbol(name) } return (