react-fontawesome
react-fontawesome copied to clipboard
Add support for DuoTone
Is your feature request related to a problem? Please describe. Add support for DuoTone, as announced by https://blog.fontawesome.com/introducing-duotone/
Describe the solution you'd like Updating the component to support the various features listed in the blog post
Describe alternatives you've considered The alternative is to glom classes onto the component
Additional context Add any other context or screenshots about the feature request here.
I believe this cheatsheet covers the specific duotone functionality that needs to be accounted for in React Font Awesome. There are 4 new custom properties and 1 new class.
--fa-primary-opacity
--fa-secondary-opacity
--fa-primary-color
--fa-secondary-color
fa-swap-opacity
I am paying for PRO and can't use it because it was not simultaneously released in all FontAwesome packages. 🤦♂
@ivosabev
You can use it right now. However, if you want to change colours and opacity to something other than the defaults applied by duotone styling, you have to use class selectors rather than attributes.
Install
npm i --save @fortawesome/pro-duotone-svg-icons
Import
import { faTimes } from '@fortawesome/pro-duotone-svg-icons';
Style
In css
.my-icon .fa-primary {
fill: #1a237e;
opacity: 0.5;
}
.my-icon .fa-secondary {
fill: #c62828;
opacity: 0.8;
}
<FontAwesomeIcon className="my-icon" icon={faTimes} />
This should be somewhere in the docs, also props support was what I was originally looking for. Thanks!
Is there a timeline for release on this? We're at the three week mark or so now from the release of Duotones but it's awfully quiet in here.
My concern is how can I use "far" as well as "fad" together? If I import it as
import { faTimes } from '@fortawesome/pro-duotone-svg-icons';
and now I also want faTimes from regular, so I'll import it again, correct?
import { faTimes } from '@fortawesome/pro-regular-svg-icons';
This creates a conflict. I can surely import this one using 'as' like following
import { faTimes as faRegularTimes} from '@fortawesome/pro-regular-svg-icons';
But then the problem is with library.add(). If I add them both, like library.add(faTimes, faRegularTimes);
will the library be able to understand what name to lookup?
For example if I call something like this
<FontAwesomeIcon icon="['far', 'times']"/>
will it be able to know that I'm calling the regular one, not the doutone one?
I'm sorry I'm not an expert in ReactJs. I tried this method through guess work and it doesn't seem to work.
@prabhat1992 Yes, if you import { faTimes as faTimesSolid } from ...
and import { faTimes as faTimesDuo } from ...
, you can add both to the library and it'll work.
The reason you can't get it to work is that you're supplying the array as a string <FontAwesomeIcon icon="['far', 'times']"/>
when you should supply it as an object:
<FontAwesomeIcon icon={['far', 'times']}/>
For the colors you can do for example:
<FontAwesomeIcon
icon={['fad', 'stroopwafel']}
size="4x"
style={{ '--fa-primary-color': 'red' }}
/>
This has been released in 0.1.5
@robmadole this shouldn't be closed IMHO; since it's only partly addressed. swapOpacity was implemented, but nothing about colors
@cyrilchapon color works using CSS as documented here. Were you expecting something else?
@robmadole,
Were you expecting something else? Yes actually ! this behavior is pretty different from how
color
works... doesn't it ?
IMHO, keeping color
(mapped to css color
or --primary-color
) depending on the case, somehow), and adding secondaryColor
, primaryOpacity
, secondaryOpacity
would be preferable.
Opacities can be more discussed, I have to say; but definately --primary-color
and --secondary-color
sound strange for React users.
The use-case and the friction is real. I'm using "react-fontawesome" for a while now, and my designer just asked us to display a duotone one. I faced this friction
@cyrilchapon those are CSS Custom Properties so while that syntax (--fa-primary-color
) may feel strange is part of the spec.
I'm resisting quite strongly adding a component prop like primaryColor
or secondaryOpacity
because it would simply mask the underlying technology. What I've seen so far is there is an objection from a lot of devs and designers to use the inline style
to set these custom properties on the icon:
<FontAwesomeIcon icon={['fad', 'stroopwafel']} style={{ '--fa-primary-color': 'eggplant' }} />
This resistance is healthy and usually leads to organizing the custom properties in an external CSS file, using Styled-Components, or Webpack-assisted CSS Modules. This is better than inline styling.
What are your thoughts on this? What did you end up doing to implement the color?
is part of the spec
The core font-awesome spec, actualy. What I'm challenging is the React wrapper spec.
it would simply mask the underlying technology So as for raw
color
(no duotone icons) which has been done for months now, isn't it ?
And actually; "masking the underlying tech" is... the point of a wrapper, in a certain way. I got your point, but IMHO it would just be a helper (just like color
); overridable via css with the core spec.
This resistance is healthy and usually leads to organizing the custom properties in an external CSS file, using Styled-Components, or Webpack-assisted CSS Modules. This is better than inline styling.
"Better" is a point of view. I challenge this one, even if your point is a great one. It's "better" in term of performance and asset-sizing only. But still; your point is applicable to color
. And still, it wouldn't disallow someone to use such a technology to compress the styles. It's not "better" at all in terms of consistency. When you have transform
, size
and color
defined as props; and you want to change the color; you would go through css-in-js in your mind ? Well, the context you describe is exactly mine, I'm using emotion.js for now, which is a powerful css-in-js technology. I compress every style through classes in my project (with some styled()
component, and css
templates that leads to classes); but I tell you : I made the choice to explicitly use style
just for the line of code of the FontAwesome Icon, for the sake of simplicity, and consistency. Just because putting some css-in-js here would lead to some crazy syntax / props passing / hoisting need that one just to want to tweak an icon color. This is only a point of view, but this is another one.
When I say "spec" I'm actually referring to this.
And actually; "masking the underlying tech" is... the point of a wrapper, in a certain way. I got your point, but IMHO it would just be a helper (just like color); overridable via css with the core spec.
Not if masking the underlying tech is harmful to overall development. And this is where the difference comes for me and why I push back against adding it like transform
or size
. I would consider it an anti-pattern to use a primaryColor
component property when better solutions should be encouraged.
"Better" is a point of view
Absolutely. And I appreciated you taking the time to explain your use case.
When you have transform, size and color defined as props; and you want to change the color; you would go through css-in-js in your mind ?
The vital part of this is that Duotone introduces the use of something completely new to Font Awesome: CSS Custom Properties. So this is less to do with how a developer deals with Font Awesome and its use of custom properties but custom properties for their entire project. What would be inconsistent is to be required to learn every custom component API that exposes component props for setting CSS Custom Properties. Using custom properties should be consistent across the project (however that decision is made; inline styles, helpers, CSS Modules, emotion.js, etc.)
I made the choice to explicitly use style just for the line of code of the FontAwesome Icon, for the sake of simplicity, and consistency. Just because putting some css-in-js here would lead to some crazy syntax / props passing / hoisting need that one just to want to tweak an icon color.
I would love to see an example of this craziness. In my mind it shouldn't be any different than setting any other CSS property like "color" or "margin" or "font-size". Maybe I'm missing something?
(re-opening this issue since you have made some great points)
What would be inconsistent is to be required to learn every custom component API that exposes component props for setting CSS Custom Properties.
I'm sorry if I'm missing something here, but why is that any different than being required to learn every CSS Customer property directly? Component props do autocomplete in editors like Code, inline CSS Custom Properties don't (for me, I'm not sure that's for everyone the case).
In my personal experience: if these were a prop, I'd have been able to guess them. Now I had to look around for an efficient way to do this which I only found in this issue.
I share the same sentiment as @Studio384 so I made a workaround component in TypeScript:
import React from 'react';
import { FontAwesomeIcon, FontAwesomeIconProps } from '@fortawesome/react-fontawesome';
interface IDuotoneFontAwesomeIconProps extends FontAwesomeIconProps {
primaryColor?: string,
secondaryColor?: string
}
type TFontAwesomeProperties = {
'--fa-primary-color'?: string,
'--fa-secondary-color'?: string,
}
export function DuotoneFontAwesomeIcon(props: IDuotoneFontAwesomeIconProps) {
const primaryColor: string | undefined = props.primaryColor;
const secondaryColor: string | undefined = props.secondaryColor;
const style: (React.CSSProperties & TFontAwesomeProperties) = props.style ? {...props.style} : {};
style['--fa-primary-color'] = primaryColor;
style['--fa-secondary-color'] = secondaryColor;
return (
<FontAwesomeIcon
{ ...props }
style={ style }
/>
)
}
With this workaround, you can use the following:
<DuotoneFontAwesomeIcon
icon={faSomeCoolIcon}
primaryColor={'#F0F'}
secondaryColor={'#0FF'}
/>
While it's not an ideal solution by any means, it prevents me from accidentally mistyping a CSS property name and offers code completion in WebStorm. I agree that not every variant of an icon should have its own set of properties to learn; however, if the icon adds significant functionality (which I believe duotone icons do), then I would prefer that significant functionality to be explicitly defined.
I don't agree that separating primary and secondary colors into a prop is an anti-pattern; I don't see the difference between this and the existing color
prop. If there is an anti-pattern here, its passing custom/faux CSS style attributes as pseudo-props. A quick alternative is to allow a string prop or an object prop with primary and secondary defined, however that results in primary/secondary being ambiguous for non-duotone icons.
Additionally, TypeScript users will see errors about non-standard prop style keys as they are not part of the standard CSSProperties type object. This can be mitigated by FontAwesome adding custom attributes to the style?: CSSProperties
definition on the FontAwesomeIconProps
itself which may offer an interim solution to the issue as a whole although I maintain that custom/faux CSS styles are not the 'React' way to do this.
All a matter of taste in the end, but thank you and your team for duotone icons as whole, they're a refreshing take on icons!
Is it possible to just add the functionality that already exist in react-native-fontawesome?
Duotone
<FontAwesomeIcon icon="coffee" color="blue" secondaryColor="red" secondaryOpacity={ 0.4 } />
You can specify the color and opacity for Duotone's secondary layer using the secondaryColor and secondaryOpacity props. Note that these are optional, and will simply default to using your primary color at 40% opacity.
https://github.com/FortAwesome/react-native-fontawesome#duotone
so seems like it's still not resolved? Any updates on this?
@pasevin what kind of update are you looking for?
@pasevin what kind of update are you looking for?
What @bolarson said gets my vote
Seems not to be a priority :(
We are not going to add props to control CSS custom properties. I'm closing this since this component supports Duotone icons already.
If users want to use properties to control this they will have to write their own wrappers around the component.
I share the same sentiment as @Studio384 so I made a workaround component in TypeScript:
import React from 'react'; import { FontAwesomeIcon, FontAwesomeIconProps } from '@fortawesome/react-fontawesome'; interface IDuotoneFontAwesomeIconProps extends FontAwesomeIconProps { primaryColor?: string, secondaryColor?: string } type TFontAwesomeProperties = { '--fa-primary-color'?: string, '--fa-secondary-color'?: string, } export function DuotoneFontAwesomeIcon(props: IDuotoneFontAwesomeIconProps) { const primaryColor: string | undefined = props.primaryColor; const secondaryColor: string | undefined = props.secondaryColor; const style: (React.CSSProperties & TFontAwesomeProperties) = props.style ? {...props.style} : {}; style['--fa-primary-color'] = primaryColor; style['--fa-secondary-color'] = secondaryColor; return ( <FontAwesomeIcon { ...props } style={ style } /> ) }
With this workaround, you can use the following:
<DuotoneFontAwesomeIcon icon={faSomeCoolIcon} primaryColor={'#F0F'} secondaryColor={'#0FF'} />
Thank you @JohnPersano ! This works beautifully!! I was even able to follow your example to add in primary and secondary opacitys!! (not sure if I spelled that right)
But in my app, I was able to swap the looks of the icon on click like so: