react icon indicating copy to clipboard operation
react copied to clipboard

Support name-based dynamic icon imports

Open ajmnz opened this issue 9 months ago • 4 comments

👋

It could be interesting to introduce a new DynamicIcon that dynamically imports and renders icons based on its name.

const CategoryList: React.FC = () => {
  const { data: categories } = api.categories.list.useQuery();

  return (
    <div>
      {categories?.map((category) => <DynamicIcon name={category.icon} />)}
    </div>
  );
}

Use case

This is useful for scenarios where the icon name is not known ahead of time (i.e. comes from an external source — backend, api, etc.) and does not affect tree-shaking, unlike doing import * as ....

Examples

Implementation

I think Lucide's implementation works quite good. They export a big lookup table of all icons and their respective dynamic import, which will be called when rendering the component.

They also accept a fallback component for when the icon hasn't loaded yet or if the name is invalid. Out of experience, it works quite well.

const dynamicImportMap = {
  "a-arrow-down": () => import('./icons/a-arrow-down.js'),
  "a-arrow-up": () => import('./icons/a-arrow-up.js'),
  // ...
}

ajmnz avatar Mar 05 '25 15:03 ajmnz

You can do dynamic imports in TypeScript like so:

export type PhosphorIcon = keyof Omit<
  typeof import("@phosphor-icons/react/dist/ssr"),
  "SSRBase"
>;

function DynamicIcon({ icon }: { icon: PhosphorIcon }) {
  const Icon = dynamic(
    () => import("@phosphor-icons/react").then((mod) => mod[icon]),
    {
      ssr: false,
    }
  );
  return <Icon size={20} weight="bold" />;
}

aidinio avatar May 13 '25 19:05 aidinio

Can you share sample code for usage? @aidinio

I guess this is how:

<DynamicIcon icon="a-arrow-up" />

ramazansancar avatar May 27 '25 08:05 ramazansancar

Can you share sample code for usage? @aidinio

I guess this is how:

An example usage would be:

<DynamicIcon icon="ArrowUp" />

If you have code completion, it should show you a list of available options given that the icon property is typed.

aidinio avatar May 27 '25 09:05 aidinio

Thanks @aidinio

ramazansancar avatar May 29 '25 08:05 ramazansancar