phosphor-react-native icon indicating copy to clipboard operation
phosphor-react-native copied to clipboard

`classNames` not applied to icons

Open brunobely opened this issue 11 months ago • 6 comments

Looks like #62 addressed that, but I think because IconBase explicitly passes a className to the main <Svg> component then any other classNames passed to the icons never makes it to the UI:

https://github.com/duongdev/phosphor-react-native/blob/85b8b5d1867e71e2737823b86c6fe43847910b74/src/lib/icon-base.tsx#L48

Maybe if instead it was

      className={`${name}-${weight}__svg-icon-phosphor ${props.className ?? ''}`}

or something similar?

brunobely avatar Feb 09 '25 15:02 brunobely

Hi @brunobely do you have a use case where you'd need a custom className? Because with nativewind for example, the recommended way is to use cssInterop. Something like :

import type { Icon as PhosphorIcon } from 'phosphor-react-native'
import { cssInterop } from 'nativewind'

import AirplaneTilt from 'phosphor-react-native/src/icons/AirplaneTilt'

export function iconWithClassName(...phosphorIcons: PhosphorIcon[]) {
  phosphorIcons.forEach((icon) => {
    cssInterop(icon, {
      className: {
        target: 'style',
        nativeStyleToProp: {
          color: true,
        },
      },
    })
  })
}

iconWithClassName(AirplaneTilt, ...)

export {AirplaneTilt, ...}

I use this in one of my projects to apply color. I still use the size as it, and i think you can also interop opacity.

mrkpatchaa avatar Feb 09 '25 15:02 mrkpatchaa

Ah, got it! I guess I was just hoping there was an automatic way to do it but I'll use that.

brunobely avatar Feb 09 '25 15:02 brunobely

It might be useful if you need to pass something else than color or opacity. But if you check the default Svg component, it doesn't have a className prop. So passing it won't have an effect I think. It's worth testing BTW. Hopefully I will have time this week to do it.

mrkpatchaa avatar Feb 09 '25 16:02 mrkpatchaa

Check this https://www.nativewind.dev/tailwind/svg/fill

React Native does not have SVG components but universal SVG support can be achieved with 3rd party libraries such as react-native-svg. While these docs use react-native-svg, the concept applies to all libraries.

You will need to cssInterop() on these components to properly style them for native.

mrkpatchaa avatar Feb 09 '25 16:02 mrkpatchaa

Is there a way to do something similar for IconContext.Provider? It doesn't seem to like className either. Could we just ship this package with an option to automatically add a peer-dep cssInterop call to the context and icons?

I had to use it like this, otherwise TypeScript still complained about className missing from IconProps:

import { cssInterop } from 'nativewind';
import type { Icon as PhosphorIcon } from 'phosphor-react-native';
import {
  AirplaneTilt as AirplaneTilt_,
  // ...
} from 'phosphor-react-native';

export function iconWithClassName(...phosphorIcons: PhosphorIcon[]) {
  return phosphorIcons.map((icon) =>
    cssInterop(icon, {
      className: {
        target: 'style',
        nativeStyleToProp: {
          color: true,
        },
      },
    })
  );
}

const icons = [AirplaneTilt_/*, ...*/];
const [AirplaneTilt/*, ...*/] = iconWithClassName(
  ...icons
);

export { AirplaneTilt/*, ...*/ };

brunobely avatar Mar 30 '25 16:03 brunobely

Hi @brunobely can you please share a reproducible example. I can't imagine a use case for that. Do you want to pass a default class to the icons with the context?

mrkpatchaa avatar Mar 30 '25 17:03 mrkpatchaa