Thanks, I tried the OpacityMask again as you suggested and it works now. It took me a bit to get it right, because i) I had a warning about the recursive property in ShaderEffectSource needing to be set to "true" and ii) the mask size needs to be the same as the source size for it to work properly. After a while I noticed that i) originated from some code in the contentItem of the button using the ColorOverlay (in fact it was the same problem there i.e. I tried to apply it to the parent). To fix ii) I used a transparent frame so that the code now looks something like: