Image: tintColor style does not work in Safari browser
The problem I am using the tintColor property to change the white color to pink when the icon is selected, on mobile and in all browsers except safari, the behavior works fine, but in safari, sometimes it changes, sometimes not.... It is usually more the ones that does not work, for example, a first time it changes to pink, but then it can never return to white, or vice versa.
How to reproduce
Simplified test case: https://codesandbox.io/s/wonderful-neumann-04vuz
Steps to reproduce:
- Enter the sandbox code on the Safari browser
- Click any image to change the index, and check the text to see the click make a difference
Expected behavior
the color of the images should change from black to red or vice versa, depending on the case.
Environment (include versions). Did this work in previous versions?
- React Native for Web (version): 0.15
- React (version): 16.11
- React Native(version): 0.63.3
- Browser: Safari
Additional context
The problem I'm only finding in safari, I've been checking the library code and I didn't find anything strange, I tried to make improvements and nothing worked... Checking from the web inspector I realized that what doesn't change is the <Filter> ID.

Some further observations regarding this issue:
The feFlood element has “unknown” support in Safari: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFlood
The flood-colour attribute does change to the correct color, but Safari doesn’t redraw the image.
Some further observations regarding this issue:
The feFlood element has “unknown” support in Safari: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feFlood
The flood-colour attribute does change to the correct color, but Safari doesn’t redraw the image.
Good observation, we need to wait for change
This can be "fixed" with a canvas implementation. @necolas would that be too much? (I can try o draft a PR)
Here is a version of my code (I use it a little differently, wrapping the canvas in a Box from @mobily/stacks) so I can pass more props/styles It seems to work fine, maybe it helps anyone 🤗
const TintedImage = ({ source, width, height, tintColor }) => {
const id = useMemo(() => {
return _.random(0, 1000000);
}, []);
React.useEffect(() => {
function draw() {
// draw image
ctx.drawImage(this, 0, 0, width, height);
// set composite mode
ctx.globalCompositeOperation = 'source-in';
// draw color
ctx.fillStyle = tintColor;
ctx.fillRect(0, 0, width, height);
}
var img = new Image(); // This is the html Image, if you import Image from RNW you need to rename it like import {Image as RNWImage} from 'react-native'"
img.onload = draw;
img.src = source;
var c = document.getElementById(`c_${id}`);
var ctx = c.getContext('2d');
});
return (
<canvas id={`c_${id}`} width={width} height={height} />
);
};
this would be superhelpful +1. Having to upload a new icon for each color is not great.
We've stopped using the built-in tintColor behavior due to this bug, but for those looking for a workaround we've been slinging around SVG data URIs that we can run through a string find/replace to update colors before rendering. Works well enough if you're ok baking your SVG data into your JS.
tint color would be a lot nicer for library users IMO
Maybe the tint color could be converted to a CSS filter for safari? https://isotropic.co/tool/hex-color-to-css-filter/
Relating workaround https://github.com/necolas/react-native-web/issues/548
Apple finally fixed the underlying bug in Safari 16.4!
SVG Resolved Issues: Fixed changes to the filter property getting ignored.
Full release notes: https://developer.apple.com/documentation/safari-release-notes/safari-16_4-release-notes#Resolved-Issues