feat: add disabledButtonTintColor prop in ActionSheetIOS (#46883)

Summary:
### Problem
Setting the `tintColor` prop in ActionSheetIOS also changes the tint of disabled entries. This could make them visually indistinguishable from enabled items. The degree to which they are indistinguishable depends on the tint color.

### Solution
This new prop `disabledButtonTintColor` allows customization of disabled items' tint color.

Related PR: https://github.com/facebook/react-native/pull/31972

## Changelog:

[IOS] [ADDED] - added `disabledButtonTintColor` prop to ActionSheetIOS

Pull Request resolved: https://github.com/facebook/react-native/pull/46883

Test Plan:
Tested in RNTester project.

<table>
  <tr>
    <td align="center">
      <strong>Before</strong>
    </td>
    <td align="center">
      <strong>After</strong>
    </td>
  </tr>
  <tr>
    <td>
      <img src="https://github.com/user-attachments/assets/5ab251d9-3128-45e0-bb1f-907376422df0" alt="Screenshot Before" width="300"/>
    </td>
    <td>
      <img src="https://github.com/user-attachments/assets/96f76a08-bb8d-497a-9c89-dca0e0bdbcbb" alt="Screenshot After" width="300"/>
    </td>
  </tr>
  <tr>
    <td align="center">
      <strong>Before</strong>
    </td>
    <td align="center">
      <strong>After</strong>
    </td>
  </tr>
</table>

Reviewed By: lunaleaps

Differential Revision: D65757069

Pulled By: cipolleschi

fbshipit-source-id: 1f51ed6927bfb4fe4e21018c541303dff44b2217
This commit is contained in:
Henning Hall 2024-11-18 05:26:38 -08:00 committed by Facebook GitHub Bot
parent 7be98c99bd
commit 089c87e22e
6 changed files with 75 additions and 1 deletions

View File

@ -22,6 +22,7 @@ export interface ActionSheetIOSOptions {
anchor?: number | undefined;
tintColor?: ColorValue | ProcessedColorValue | undefined;
cancelButtonTintColor?: ColorValue | ProcessedColorValue | undefined;
disabledButtonTintColor?: ColorValue | ProcessedColorValue | undefined;
userInterfaceStyle?: 'light' | 'dark' | undefined;
disabledButtonIndices?: number[] | undefined;
}

View File

@ -49,6 +49,7 @@ const ActionSheetIOS = {
+anchor?: ?number,
+tintColor?: ColorValue | ProcessedColorValue,
+cancelButtonTintColor?: ColorValue | ProcessedColorValue,
+disabledButtonTintColor?: ColorValue | ProcessedColorValue,
+userInterfaceStyle?: string,
+disabledButtonIndices?: Array<number>,
|},
@ -64,6 +65,7 @@ const ActionSheetIOS = {
const {
tintColor,
cancelButtonTintColor,
disabledButtonTintColor,
destructiveButtonIndex,
...remainingOptions
} = options;
@ -77,6 +79,10 @@ const ActionSheetIOS = {
const processedTintColor = processColor(tintColor);
const processedCancelButtonTintColor = processColor(cancelButtonTintColor);
const processedDisabledButtonTintColor = processColor(
disabledButtonTintColor,
);
invariant(
processedTintColor == null || typeof processedTintColor === 'number',
'Unexpected color given for ActionSheetIOS.showActionSheetWithOptions tintColor',
@ -86,6 +92,11 @@ const ActionSheetIOS = {
typeof processedCancelButtonTintColor === 'number',
'Unexpected color given for ActionSheetIOS.showActionSheetWithOptions cancelButtonTintColor',
);
invariant(
processedDisabledButtonTintColor == null ||
typeof processedDisabledButtonTintColor === 'number',
'Unexpected color given for ActionSheetIOS.showActionSheetWithOptions disabledButtonTintColor',
);
RCTActionSheetManager.showActionSheetWithOptions(
{
...remainingOptions,
@ -93,6 +104,8 @@ const ActionSheetIOS = {
tintColor: processedTintColor,
// $FlowFixMe[incompatible-call]
cancelButtonTintColor: processedCancelButtonTintColor,
// $FlowFixMe[incompatible-call]
disabledButtonTintColor: processedDisabledButtonTintColor,
destructiveButtonIndices,
},
callback,

View File

@ -12,6 +12,7 @@ exports[`public API should not change unintentionally Libraries/ActionSheetIOS/A
+anchor?: ?number,
+tintColor?: ColorValue | ProcessedColorValue,
+cancelButtonTintColor?: ColorValue | ProcessedColorValue,
+disabledButtonTintColor?: ColorValue | ProcessedColorValue,
+userInterfaceStyle?: string,
+disabledButtonIndices?: Array<number>,
|},

View File

@ -98,6 +98,8 @@ RCT_EXPORT_METHOD(showActionSheetWithOptions
UIColor *tintColor = [RCTConvert UIColor:options.tintColor() ? @(*options.tintColor()) : nil];
UIColor *cancelButtonTintColor =
[RCTConvert UIColor:options.cancelButtonTintColor() ? @(*options.cancelButtonTintColor()) : nil];
UIColor *disabledButtonTintColor =
[RCTConvert UIColor:options.disabledButtonTintColor() ? @(*options.disabledButtonTintColor()) : nil];
NSString *userInterfaceStyle = [RCTConvert NSString:options.userInterfaceStyle()];
dispatch_async(dispatch_get_main_queue(), ^{
@ -114,6 +116,7 @@ RCT_EXPORT_METHOD(showActionSheetWithOptions
@"anchor" : anchor ?: @"(null)",
@"tintColor" : tintColor ?: @"(null)",
@"cancelButtonTintColor" : cancelButtonTintColor ?: @"(null)",
@"disabledButtonTintColor" : disabledButtonTintColor ?: @"(null)",
@"disabledButtonIndices" : disabledButtonIndices ?: @"(null)",
});
return;
@ -166,7 +169,11 @@ RCT_EXPORT_METHOD(showActionSheetWithOptions
if (disabledButtonIndices) {
for (NSNumber *disabledButtonIndex in disabledButtonIndices) {
if ([disabledButtonIndex integerValue] < buttons.count) {
[alertController.actions[[disabledButtonIndex integerValue]] setEnabled:false];
UIAlertAction *action = alertController.actions[[disabledButtonIndex integerValue]];
[action setEnabled:false];
if (disabledButtonTintColor) {
[action setValue:disabledButtonTintColor forKey:@"titleTextColor"];
}
} else {
RCTLogError(
@"Index %@ from `disabledButtonIndices` is out of bounds. Maximum index value is %@.",

View File

@ -24,6 +24,7 @@ export interface Spec extends TurboModule {
+anchor?: ?number,
+tintColor?: ?number,
+cancelButtonTintColor?: ?number,
+disabledButtonTintColor?: ?number,
+userInterfaceStyle?: ?string,
+disabledButtonIndices?: Array<number>,
|},
@ -37,6 +38,7 @@ export interface Spec extends TurboModule {
+anchor?: ?number,
+tintColor?: ?number,
+cancelButtonTintColor?: ?number,
+disabledButtonTintColor?: ?number,
+excludedActivityTypes?: ?Array<string>,
+userInterfaceStyle?: ?string,
|},

View File

@ -155,6 +155,50 @@ class ActionSheetCancelButtonTintExample extends React.Component<
};
}
class ActionSheetDisabledButtonTintExample extends React.Component<
$FlowFixMeProps,
$FlowFixMeState,
> {
state: any | {clicked: string} = {
clicked: 'none',
};
render(): React.Node {
return (
<RNTesterThemeContext.Consumer>
{theme => (
<View>
<Text
onPress={this.showActionSheet}
style={[style.button, {color: theme.SecondaryLabelColor}]}>
Click to show the ActionSheet
</Text>
<Text style={{color: theme.SecondaryLabelColor}}>
Clicked button: {this.state.clicked}
</Text>
</View>
)}
</RNTesterThemeContext.Consumer>
);
}
showActionSheet = () => {
ActionSheetIOS.showActionSheetWithOptions(
{
options: BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
destructiveButtonIndex: DESTRUCTIVE_INDEX,
disabledButtonIndices: DISABLED_BUTTON_INDICES,
tintColor: 'black',
disabledButtonTintColor: 'gray',
},
buttonIndex => {
this.setState({clicked: BUTTONS[buttonIndex]});
},
);
};
}
class ActionSheetAnchorExample extends React.Component<
$FlowFixMeProps,
$FlowFixMeState,
@ -480,6 +524,12 @@ exports.examples = [
return <ActionSheetCancelButtonTintExample />;
},
},
{
title: 'Show Action Sheet with disabled tinted button',
render(): React.MixedElement {
return <ActionSheetDisabledButtonTintExample />;
},
},
{
title: 'Show Action Sheet with anchor',
render(): React.MixedElement {