Skip to content

Commit 3d08683

Browse files
feat(JS): background-size, position and repeat styles (#52284)
Summary: This PR adds support for background size, position and repeat styles. It follows the [CSS](https://www.w3.org/TR/css-backgrounds-3/#backgrounds) spec. Currently we default to `background-origin: padding-box` and `background-clip : border-box` to match the web's behavior. We can introduce these styles later. I have split the PR intro three parts for review. This PR includes JS parsing and style propagation to native changes. I wanted to introduce one style at a time, but CSS spec is such that size, position and repeat are intertwined. ## Changelog: [GENERAL][ADDED] - Background size, position and repeat styles. <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: #52284 Test Plan: Merge the [iOS](#52283) and [android](#52282) PR into this, this PR includes `BackgroundImageExample`. I have also added testcases for parsing syntax in JS. https://github.com/user-attachments/assets/b7192fdf-52ba-4eb0-a1be-d47c72d87e92 Reviewed By: joevilches Differential Revision: D82973282 Pulled By: jorge-cab fbshipit-source-id: a94e33962c6708be963e1cac049da50d4764da64
1 parent e859293 commit 3d08683

File tree

13 files changed

+2003
-4
lines changed

13 files changed

+2003
-4
lines changed

packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import type {AnyAttributeType} from '../../Renderer/shims/ReactNativeTypes';
1313
import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
1414
import processAspectRatio from '../../StyleSheet/processAspectRatio';
1515
import processBackgroundImage from '../../StyleSheet/processBackgroundImage';
16+
import processBackgroundPosition from '../../StyleSheet/processBackgroundPosition';
17+
import processBackgroundRepeat from '../../StyleSheet/processBackgroundRepeat';
18+
import processBackgroundSize from '../../StyleSheet/processBackgroundSize';
1619
import processBoxShadow from '../../StyleSheet/processBoxShadow';
1720
import processColor from '../../StyleSheet/processColor';
1821
import processFilter from '../../StyleSheet/processFilter';
@@ -144,11 +147,25 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
144147
: {process: processBoxShadow},
145148

146149
/**
147-
* Linear Gradient
150+
* BackgroundImage
148151
*/
149-
experimental_backgroundImage: ReactNativeFeatureFlags.enableNativeCSSParsing()
150-
? true
151-
: {process: processBackgroundImage},
152+
experimental_backgroundImage: {process: processBackgroundImage},
153+
154+
/**
155+
* BackgroundSize
156+
*/
157+
experimental_backgroundSize: {process: processBackgroundSize},
158+
159+
/**
160+
* BackgroundPosition
161+
*/
162+
experimental_backgroundPosition: {process: processBackgroundPosition},
163+
164+
/**
165+
* BackgroundRepeat
166+
*/
167+
experimental_backgroundRepeat: {process: processBackgroundRepeat},
168+
152169
/**
153170
* View
154171
*/

packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ const validAttributesForNonEventProps = {
182182
experimental_backgroundImage: ReactNativeFeatureFlags.enableNativeCSSParsing()
183183
? (true as const)
184184
: {process: require('../StyleSheet/processBackgroundImage').default},
185+
experimental_backgroundSize: {
186+
process: require('../StyleSheet/processBackgroundSize').default,
187+
},
188+
experimental_backgroundPosition: {
189+
process: require('../StyleSheet/processBackgroundPosition').default,
190+
},
191+
experimental_backgroundRepeat: {
192+
process: require('../StyleSheet/processBackgroundRepeat').default,
193+
},
185194
boxShadow: ReactNativeFeatureFlags.enableNativeCSSParsing()
186195
? (true as const)
187196
: {process: require('../StyleSheet/processBoxShadow').default},

packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ const ReactNativeStyleAttributes =
1717
const resolveAssetSource = require('../Image/resolveAssetSource').default;
1818
const processBackgroundImage =
1919
require('../StyleSheet/processBackgroundImage').default;
20+
const processBackgroundPosition =
21+
require('../StyleSheet/processBackgroundPosition').default;
22+
const processBackgroundRepeat =
23+
require('../StyleSheet/processBackgroundRepeat').default;
24+
const processBackgroundSize =
25+
require('../StyleSheet/processBackgroundSize').default;
2026
const processColor = require('../StyleSheet/processColor').default;
2127
const processColorArray = require('../StyleSheet/processColorArray').default;
2228
const processFilter = require('../StyleSheet/processFilter').default;
@@ -203,6 +209,12 @@ function getProcessorForType(typeName: string): ?(nextProp: any) => any {
203209
return processFilter;
204210
case 'BackgroundImage':
205211
return processBackgroundImage;
212+
case 'BackgroundPosition':
213+
return processBackgroundPosition;
214+
case 'BackgroundRepeat':
215+
return processBackgroundRepeat;
216+
case 'BackgroundSize':
217+
return processBackgroundSize;
206218
case 'ImageSource':
207219
return resolveAssetSource;
208220
case 'BoxShadow':

packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,43 @@ type RadialGradientValue = {
779779

780780
export type BackgroundImageValue = LinearGradientValue | RadialGradientValue;
781781

782+
export type BackgroundSizeValue =
783+
| {
784+
x: string | number,
785+
y: string | number,
786+
}
787+
| 'cover'
788+
| 'contain';
789+
790+
export type BackgroundRepeatKeyword =
791+
| 'repeat'
792+
| 'space'
793+
| 'round'
794+
| 'no-repeat';
795+
796+
export type BackgroundPositionValue =
797+
| {
798+
top: number | string,
799+
left: number | string,
800+
}
801+
| {
802+
top: number | string,
803+
right: number | string,
804+
}
805+
| {
806+
bottom: number | string,
807+
left: number | string,
808+
}
809+
| {
810+
bottom: number | string,
811+
right: number | string,
812+
};
813+
814+
export type BackgroundRepeatValue = {
815+
x: BackgroundRepeatKeyword,
816+
y: BackgroundRepeatKeyword,
817+
};
818+
782819
export type BoxShadowValue = {
783820
offsetX: number | string,
784821
offsetY: number | string,
@@ -853,6 +890,13 @@ export type ____ViewStyle_InternalBase = $ReadOnly<{
853890
filter?: $ReadOnlyArray<FilterFunction> | string,
854891
mixBlendMode?: ____BlendMode_Internal,
855892
experimental_backgroundImage?: $ReadOnlyArray<BackgroundImageValue> | string,
893+
experimental_backgroundSize?: $ReadOnlyArray<BackgroundSizeValue> | string,
894+
experimental_backgroundPosition?:
895+
| $ReadOnlyArray<BackgroundPositionValue>
896+
| string,
897+
experimental_backgroundRepeat?:
898+
| $ReadOnlyArray<BackgroundRepeatValue>
899+
| string,
856900
isolation?: 'auto' | 'isolate',
857901
}>;
858902

0 commit comments

Comments
 (0)