diff --git a/Libraries/StyleSheet/PlatformColorValueTypes.ios.js b/Libraries/StyleSheet/PlatformColorValueTypes.ios.js index 883f86e97cd316..193ea338bdffc5 100644 --- a/Libraries/StyleSheet/PlatformColorValueTypes.ios.js +++ b/Libraries/StyleSheet/PlatformColorValueTypes.ios.js @@ -16,6 +16,8 @@ export opaque type NativeColorValue = { dynamic?: { light: ?(ColorValue | ProcessedColorValue), dark: ?(ColorValue | ProcessedColorValue), + highContrastLight?: ?(ColorValue | ProcessedColorValue), + highContrastDark?: ?(ColorValue | ProcessedColorValue), }, }; @@ -26,12 +28,21 @@ export const PlatformColor = (...names: Array): ColorValue => { export type DynamicColorIOSTuplePrivate = { light: ColorValue, dark: ColorValue, + highContrastLight?: ColorValue, + highContrastDark?: ColorValue, }; export const DynamicColorIOSPrivate = ( tuple: DynamicColorIOSTuplePrivate, ): ColorValue => { - return {dynamic: {light: tuple.light, dark: tuple.dark}}; + return { + dynamic: { + light: tuple.light, + dark: tuple.dark, + highContrastLight: tuple.highContrastLight, + highContrastDark: tuple.highContrastDark, + }, + }; }; export const normalizeColorObject = ( @@ -49,6 +60,8 @@ export const normalizeColorObject = ( dynamic: { light: normalizeColor(dynamic.light), dark: normalizeColor(dynamic.dark), + highContrastLight: normalizeColor(dynamic.highContrastLight), + highContrastDark: normalizeColor(dynamic.highContrastDark), }, }; return dynamicColor; @@ -67,6 +80,8 @@ export const processColorObject = ( dynamic: { light: processColor(dynamic.light), dark: processColor(dynamic.dark), + highContrastLight: processColor(dynamic.highContrastLight), + highContrastDark: processColor(dynamic.highContrastDark), }, }; return dynamicColor; diff --git a/Libraries/StyleSheet/PlatformColorValueTypesIOS.ios.js b/Libraries/StyleSheet/PlatformColorValueTypesIOS.ios.js index c9835a0ce140c5..912236c7359de3 100644 --- a/Libraries/StyleSheet/PlatformColorValueTypesIOS.ios.js +++ b/Libraries/StyleSheet/PlatformColorValueTypesIOS.ios.js @@ -14,8 +14,15 @@ import {DynamicColorIOSPrivate} from './PlatformColorValueTypes'; export type DynamicColorIOSTuple = { light: ColorValue, dark: ColorValue, + highContrastLight?: ColorValue, + highContrastDark?: ColorValue, }; export const DynamicColorIOS = (tuple: DynamicColorIOSTuple): ColorValue => { - return DynamicColorIOSPrivate({light: tuple.light, dark: tuple.dark}); + return DynamicColorIOSPrivate({ + light: tuple.light, + dark: tuple.dark, + highContrastLight: tuple.highContrastLight, + highContrastDark: tuple.highContrastDark, + }); }; diff --git a/Libraries/StyleSheet/PlatformColorValueTypesIOS.js b/Libraries/StyleSheet/PlatformColorValueTypesIOS.js index cfdf4ae0c0ac29..ead8c4fca2f59f 100644 --- a/Libraries/StyleSheet/PlatformColorValueTypesIOS.js +++ b/Libraries/StyleSheet/PlatformColorValueTypesIOS.js @@ -13,6 +13,8 @@ import type {ColorValue} from './StyleSheet'; export type DynamicColorIOSTuple = { light: ColorValue, dark: ColorValue, + highContrastLight?: ColorValue, + highContrastDark?: ColorValue, }; export const DynamicColorIOS = (tuple: DynamicColorIOSTuple): ColorValue => { diff --git a/Libraries/StyleSheet/__tests__/normalizeColor-test.js b/Libraries/StyleSheet/__tests__/normalizeColor-test.js index 80979e0ec2c75c..5421edccd23319 100644 --- a/Libraries/StyleSheet/__tests__/normalizeColor-test.js +++ b/Libraries/StyleSheet/__tests__/normalizeColor-test.js @@ -43,6 +43,25 @@ describe('iOS', () => { expect(normalizedColor).toEqual(expectedColor); }); + it('should normalize iOS Dynamic colors with accessible colors', () => { + const color = DynamicColorIOS({ + light: 'black', + dark: 'white', + highContrastLight: 'red', + highContrastDark: 'blue', + }); + const normalizedColor = normalizeColor(color); + const expectedColor = { + dynamic: { + light: 'black', + dark: 'white', + highContrastLight: 'red', + highContrastDark: 'blue', + }, + }; + expect(normalizedColor).toEqual(expectedColor); + }); + it('should normalize iOS Dynamic colors with PlatformColor colors', () => { const color = DynamicColorIOS({ light: PlatformColor('systemBlackColor'), diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index af47b0d353ed1a..d60b80b2dc7069 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -879,13 +879,29 @@ + (UIColor *)UIColor:(id)json UIColor *lightColor = [RCTConvert UIColor:light]; id dark = [appearances objectForKey:@"dark"]; UIColor *darkColor = [RCTConvert UIColor:dark]; + id highContrastLight = [appearances objectForKey:@"highContrastLight"]; + UIColor *highContrastLightColor = [RCTConvert UIColor:highContrastLight]; + id highContrastDark = [appearances objectForKey:@"highContrastDark"]; + UIColor *highContrastDarkColor = [RCTConvert UIColor:highContrastDark]; if (lightColor != nil && darkColor != nil) { #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 if (@available(iOS 13.0, *)) { - UIColor *color = - [UIColor colorWithDynamicProvider:^UIColor *_Nonnull(UITraitCollection *_Nonnull collection) { - return collection.userInterfaceStyle == UIUserInterfaceStyleDark ? darkColor : lightColor; - }]; + UIColor *color = [UIColor colorWithDynamicProvider:^UIColor *_Nonnull( + UITraitCollection *_Nonnull collection) { + if (collection.userInterfaceStyle == UIUserInterfaceStyleDark) { + if (collection.accessibilityContrast == UIAccessibilityContrastHigh && highContrastDarkColor != nil) { + return highContrastDarkColor; + } else { + return darkColor; + } + } else { + if (collection.accessibilityContrast == UIAccessibilityContrastHigh && highContrastLightColor != nil) { + return highContrastLightColor; + } else { + return lightColor; + } + } + }]; return color; } else { #endif diff --git a/packages/eslint-plugin-react-native-community/platform-colors.js b/packages/eslint-plugin-react-native-community/platform-colors.js index d2d720527e64a6..12e8f908f90a5d 100644 --- a/packages/eslint-plugin-react-native-community/platform-colors.js +++ b/packages/eslint-plugin-react-native-community/platform-colors.js @@ -60,7 +60,6 @@ module.exports = { const properties = args[0].properties; if ( !( - properties.length === 2 && properties[0].type === 'Property' && properties[0].key.name === 'light' && properties[1].type === 'Property' &&