# Astro で Iconify を使うべく色々格闘した話


## 結論

- `@iconify/iconify`を使って、SVG を直接生成した
- SVG の生成をラップする Astro コンポーネントを自作した

```astro title=Icon.astro showLineNumbers
---
import Iconify from "@iconify/iconify";

interface Props {
  icon: string;
  class?: string;
}

const props = Astro.props;

const getIconSvg = async (icon: string) => {
  await Iconify.loadIcon(icon);

  const iconData = Iconify.getIcon(icon);
  if (!iconData) throw new Error(`Icon ${icon} not found`);

  return (
    `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${iconData.left} ${iconData.top} ${iconData.width} ${iconData.height}" fill="none" style="width:100%">` +
    iconData.body +
    "</svg>"
  );
};
---

<div set:html={await getIconSvg(props.icon)} class={props.class} />
```

使い方:

```astro title=App.astro showLineNumbers
<Icon class="w-32" icon="fluent-emoji:robot" />
```

## 試したこと

- `astro-icon`: `iconify` のバージョンが古く、欲しいものが使えなかった。
- `@iconify/tailwind`: iconの指定に変数を利用した際になぜか Icon が表示されず使えなかった。

  ```astro title=OK
  <span class="fluent-emoji:robot" />
  ```

  ```astro title=NG
  ---
  const icon = "icon" + "-" + "[fluent-emoji--building-construction]";
  ---
  <span class={`${icon} text-8xl`}></span>
  ```

- `@iconify/react`: client サイドで javascrit を実行しないと画像が表示されないので、Astro との相性を考えて使わなかった。