Dynamic Heroicons import with Next.js

Viewed 2220

I'm using heroicons in my Next.js project and since it currently doesn't support dynamic imports (by passing icon name to component) I created my own component.

// HeroIcon.tsx
import * as SolidIcons from '@heroicons/react/solid';
import * as OutlineIcons from '@heroicons/react/outline';

interface Props {
  icon: string;
  color?: string;
  size?: number;
  outline?: boolean;
}

export const HeroIcon = (props: Props): JSX.Element => {
  const { icon, color, size, outline = false } = props;

  const { ...icons } = outline ? OutlineIcons : SolidIcons;

  // @ts-ignore
  const Icon: JSX.Element = icons[icon];

  const classes = [
    `${color ? color : 'text-black'}`,
    `h-${size ? size : 6}`,
    `w-${size ? size : 6}`
  ];

  return (
    // @ts-ignore
    <Icon className={classes.join(' ')} />
  );
};

and I can later use it as such:

<HeroIcon icon='CogIcon' color='text-blue-600' size={6} outline />

While it works on my development server: enter image description here

the moment I build the project with npm run build and start it with npm start I'm getting this result instead: enter image description here

and on mobile devices, icons are not visible at all.

The page is pre-rendered with SSG and uses both getStaticPaths and getStaticProps.

Any idea what might be the reason?

1 Answers

This code is the problem

  const classes = [
    `${color ? color : 'text-black'}`,
    `h-${size ? size : 6}`,
    `w-${size ? size : 6}`
  ];

If you want to change Tailwind CSS styles dynamically, write your code like this instead.

  const classes = [
    `${color ? color : 'text-black'}`,
    size ? 'h-12' : 'h-6',
    size ? 'w-12' : 'w-6',
  ];

This is due to how Purge CSS works, and Tailwind CSS uses Purge CSS under the hood to optimize your Tailwind CSS classes for production.

Sadly, you cannot write your class like h-{x}, since Tailwind CSS is purged at build time and h-{x} does not evaluate to valid Tailwind CSS class.


Reference
https://v2.tailwindcss.com/docs/optimizing-for-production#writing-purgeable-html

Related