feat: added `textShadow` property in `TextStyleProps`
Summary
This PR is for adding the support fortextShadow property in TextStyleProps as required in the issue https://github.com/facebook/react-native/issues/34425. Unit Test cases and an example are also added in this PR.
Changelog
[General] [added] - Added support for textShadow property in style prop for Text Component,
Test Plan
- Added unit test cases for the function
processTextShadow. - Added an example in the RNTester app.
| Platform | Engine | Arch | Size (bytes) | Diff |
|---|---|---|---|---|
| android | hermes | arm64-v8a | 7,748,211 | -20,296 |
| android | hermes | armeabi-v7a | 7,150,055 | -19,408 |
| android | hermes | x86 | 8,059,405 | -22,242 |
| android | hermes | x86_64 | 8,030,131 | -23,019 |
| android | jsc | arm64-v8a | 9,609,341 | -19,885 |
| android | jsc | armeabi-v7a | 8,374,662 | -18,994 |
| android | jsc | x86 | 9,556,814 | -21,828 |
| android | jsc | x86_64 | 10,149,163 | -22,588 |
Base commit: cb3a5cc6913d81b3e16bcb3a9d5f29e5cfa1de73 Branch: main
| Platform | Engine | Arch | Size (bytes) | Diff |
|---|---|---|---|---|
| ios | - | universal | n/a | -- |
Base commit: b5aec963404dbe48ee068cfb98e2e1a03dc64dcf Branch: main
@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.
Could you please rebase this @dhruvtailor7?
@dhruvtailor7 Could you please take care of the warnings and rebase onto main? 🙏
Textshadow can accept comma separated values. Also regex used is not maintainable easily better to read spec and follow accordingly.
https://drafts.csswg.org/css-text-decor/#text-shadow-property
Hello @jacdebug. How can I map multiple textShadow values because currently the Text Component only supports single text-shadow through props?
or, As part of this PR, should we enhance the text component on the native side to support multiple text shadows?
Textshadow can accept comma separated values. Also regex used is not maintainable easily better to read spec and follow accordingly.
https://drafts.csswg.org/css-text-decor/#text-shadow-property
Hello @necolas @jacdebug , I am not sure what would be the most optimal way to derive the textShadow values from the string. Do you have any suggestions?
Hi @dhruvtailor7, could you take care of fixing the linting errors? 🙏 As per your question:
Hello @necolas @jacdebug , I am not sure what would be the most optimal way to derive the textShadow values from the string. Do you have any suggestions?
I have a couple of ideas.
Manually splitting
One idea could be to manually try to split the string. For example, you can split it using white-spaces and then process the various pieces of the array. This will avoid to instantiate the regex every time and will make the logic more readable. Although it will make it imperative instead of declarative.
The downsides, this could be:
- An imperative approach instead of a declarative one
- It could become hard to properly handle all the use cases. @jacdebug was saying that we have also to support comma separated shadows, so the following are valid values:
'1, 1,1, red',1,1, 1,rgb(1,1,0).
Composing the regex
To address the non-maintainable part of the feedback, we can try to split the regex in something more readable and then we can combine it together. For example, we can have (I've never used JS regex, so the syntax may be wrong):
const offsetRE = '\d\.\d';
const separatorRE = '( |,)';
// other components
const fullShadow = `${offsetRE}${separato}${offsetRE}${separator}${blurRadiusRE}${separator}${colorRE}`;
const colorShadow = `${colorRE}`
return new RegEx(`${fullShadow}|...|${colorShadow}`); // concatenate in OR all the possible formats for the shadow.
This will make it readable, maintainable and we are going to keep a declarative approach.
WDYT?
so the following are valid values:
'1, 1,1, red',1,1, 1,rgb(1,1,0)
No, multiple shadows are separated by commas. You can split on comma to detect multiple shadows and print a warning that only the first shadow will be supported by RN. The trickier part will be detecting which part of the shadow is a color. Best to refer to the spec for details about the syntax
You can split on comma to detect multiple shadows
Splitting with a comma will not work when the shadow color is in rgb or hsl format. So, I guess using regex with all possible shadow formats is the only option.
Sorry, my bad... I'm not super familiar with web development. However, I think that we can rework the regex to make it more readable and maintainable as I suggested above.
The final regex could be:
const OffsetRegEx = '\d.\d';
...
const fullShadow = `${OffsetRegEx} ${OffsetRegEx} ${borderRadiusRegEx} ${ColorRegEx}`;
const shadowRegEx = `${shadowWithOnlyXOffset}|${shadowWithXAndYOffset}|...|${fullShadow}`;
return new RegEx(`${shadowRegEx}(,${shadowRegEx})+`);
At least we address the maintainability issue and we manage to parse multiple shadows. WDYT?
Splitting with a comma will not work when the shadow color is in rgb or hsl format.
Good point! I think eventually a lot of this stuff will move into native code. Note that CSS Color 4 allows space separated rgb values, which would make things easier if we didn't also have comma-separated. Ideas for another day.
Thanks for doing this. I saw that you also modified the StyleSheetTypes.js file. Could you please update the types of TypeScript also? 🙏
Thank you so much!
@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.
Thanks for doing this. I saw that you also modified the
StyleSheetTypes.jsfile. Could you please update the types of TypeScript also? 🙏Thank you so much!
@cipolleschi Updated the Typescript type definition. Thanks.
@necolas I see there are many new css properties added recently and each of then has its own css parsing. Can we use something like reworkcss/css instead, WDYT?
I think https://github.com/postcss/postcss would be a better choice. We use it for some value parsing in stylex and react-native-web. Similarly https://colorjs.io/ might be useful for colors. It depends on what you all think we should do in JS vs native code in the long term
Thanks to @javache for suggestion,
We need to reuse the logic from https://github.com/facebook/react-native/blob/main/packages/normalize-color/index.js for both color list and parsing logic.
@jacdebug I have updated the PR. Can you review it? Thanks.
@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.
This PR has some import issues. Our Flow static analyzer is reporting errors like this in several places:

These are happening here:

Could you have a look at them? To reproduce them, you can try to install and run flow locally.
Could you have a look at them? To reproduce them, you can try to install and run
flowlocally.
Hmm. I do have flow installed but I am not getting any errors.

Also if a new colour is added then do we need to update this index?
@jacdebug Yes, If the new color regex has a capturing group.
@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.
@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.
I'm sorry that this PR is taking so long to be merged. We have some internal components that use the shadow that are impacted by these changes. I haven't had the time to look into those yet.
@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.
It's alright. Thanks for the update.
I don't think we can merge while it includes a change to the normalize-color export. It will cause too much churn internally and in the ecosystem. I don't think we need to reuse its logic either. We can probably use something like postcss-value-parser to break the textShadow value down into its parts before forwarding them to the existing RN style properties.
Someone said multiple shadows, May be positioning multiple Text components on top of each other do the trick??