Skip to content

Commit

Permalink
feat: add mode prop to radio button item (#2379)
Browse files Browse the repository at this point in the history
  • Loading branch information
unikvozm committed Nov 25, 2020
1 parent 0ec3587 commit ed60fae
Show file tree
Hide file tree
Showing 5 changed files with 529 additions and 35 deletions.
2 changes: 2 additions & 0 deletions example/src/ExampleList.tsx
Expand Up @@ -36,6 +36,7 @@ import TextInputExample from './Examples/TextInputExample';
import ToggleButtonExample from './Examples/ToggleButtonExample';
import TouchableRippleExample from './Examples/TouchableRippleExample';
import ThemeExample from './Examples/ThemeExample';
import RadioButtonItemExample from './Examples/RadioButtonItemExample';

export const examples: Record<
string,
Expand Down Expand Up @@ -64,6 +65,7 @@ export const examples: Record<
progressbar: ProgressBarExample,
radio: RadioButtonExample,
radioGroup: RadioButtonGroupExample,
radioItem: RadioButtonItemExample,
searchbar: SearchbarExample,
snackbar: SnackbarExample,
surface: SurfaceExample,
Expand Down
56 changes: 56 additions & 0 deletions example/src/Examples/RadioButtonItemExample.tsx
@@ -0,0 +1,56 @@
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
import { RadioButton, Colors, useTheme } from 'react-native-paper';

const RadioButtonItemExample = () => {
const [checkedDefault, setCheckedDefault] = React.useState<boolean>(true);
const [checkedAndroid, setCheckedAndroid] = React.useState<boolean>(true);
const [checkedIOS, setCheckedIOS] = React.useState<boolean>(true);
const {
colors: { background },
} = useTheme();

return (
<View
style={[
styles.container,
{
backgroundColor: background,
},
]}
>
<RadioButton.Item
label="Default (will look like whatever system this is running on)"
status={checkedDefault ? 'checked' : 'unchecked'}
onPress={() => setCheckedDefault(!checkedDefault)}
value="default"
/>
<RadioButton.Item
label="Android"
mode="android"
status={checkedAndroid ? 'checked' : 'unchecked'}
onPress={() => setCheckedAndroid(!checkedAndroid)}
value="android"
/>
<RadioButton.Item
label="iOS"
mode="ios"
status={checkedIOS ? 'checked' : 'unchecked'}
onPress={() => setCheckedIOS(!checkedIOS)}
value="iOS"
/>
</View>
);
};

RadioButtonItemExample.title = 'Radio Button Item';

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Colors.white,
paddingVertical: 8,
},
});

export default RadioButtonItemExample;
85 changes: 50 additions & 35 deletions src/components/RadioButton/RadioButtonItem.tsx
Expand Up @@ -12,6 +12,8 @@ import { handlePress } from './utils';
import TouchableRipple from '../TouchableRipple/TouchableRipple';
import RadioButton from './RadioButton';
import Text from '../Typography/Text';
import RadioButtonAndroid from './RadioButtonAndroid';
import RadioButtonIOS from './RadioButtonIOS';

export type Props = {
/**
Expand Down Expand Up @@ -62,6 +64,11 @@ export type Props = {
* testID to be used on tests.
*/
testID?: string;
/**
* Whether `<RadioButton.Android />` or `<RadioButton.IOS />` should be used.
* Left undefined `<RadioButton />` will be used.
*/
mode?: 'android' | 'ios';
};

/**
Expand Down Expand Up @@ -106,41 +113,49 @@ const RadioButtonItem = ({
theme: { colors },
accessibilityLabel,
testID,
}: Props) => (
<RadioButtonContext.Consumer>
{(context?: RadioButtonContextType) => {
return (
<TouchableRipple
onPress={
disabled
? undefined
: () =>
handlePress({
onPress: onPress,
onValueChange: context?.onValueChange,
value,
})
}
accessibilityLabel={accessibilityLabel}
testID={testID}
>
<View style={[styles.container, style]} pointerEvents="none">
<Text style={[styles.label, { color: colors.text }, labelStyle]}>
{label}
</Text>
<RadioButton
value={value}
disabled={disabled}
status={status}
color={color}
uncheckedColor={uncheckedColor}
/>
</View>
</TouchableRipple>
);
}}
</RadioButtonContext.Consumer>
);
mode,
}: Props) => {
const radioButtonProps = { value, disabled, status, color, uncheckedColor };
let radioButton: any;

if (mode === 'android') {
radioButton = <RadioButtonAndroid {...radioButtonProps} />;
} else if (mode === 'ios') {
radioButton = <RadioButtonIOS {...radioButtonProps} />;
} else {
radioButton = <RadioButton {...radioButtonProps} />;
}

return (
<RadioButtonContext.Consumer>
{(context?: RadioButtonContextType) => {
return (
<TouchableRipple
onPress={
disabled
? undefined
: () =>
handlePress({
onPress: onPress,
onValueChange: context?.onValueChange,
value,
})
}
accessibilityLabel={accessibilityLabel}
testID={testID}
>
<View style={[styles.container, style]} pointerEvents="none">
<Text style={[styles.label, { color: colors.text }, labelStyle]}>
{label}
</Text>
{radioButton}
</View>
</TouchableRipple>
);
}}
</RadioButtonContext.Consumer>
);
};

RadioButtonItem.displayName = 'RadioButton.Item';

Expand Down
50 changes: 50 additions & 0 deletions src/components/__tests__/RadioButton/RadioButtonItem.test.js
@@ -0,0 +1,50 @@
import * as React from 'react';
import { Platform } from 'react-native';
import renderer from 'react-test-renderer';
import RadioButtonItem from '../../RadioButton/RadioButtonItem';

it('renders unchecked', () => {
const tree = renderer
.create(
<RadioButtonItem
status="unchecked"
label="Unchecked Button"
value="unchecked"
/>
)
.toJSON();

expect(tree).toMatchSnapshot();
});

it('can render the iOS radio button on different platforms', () => {
Platform.OS = 'android';
const tree = renderer
.create(
<RadioButtonItem
status="unchecked"
label="iOS Radio button"
mode="ios"
value="ios"
/>
)
.toJSON();

expect(tree).toMatchSnapshot();
});

it('can render the Android radio button on different platforms', () => {
Platform.OS = 'ios';
const tree = renderer
.create(
<RadioButtonItem
status="unchecked"
label="iOS Checkbox"
mode="android"
value="android"
/>
)
.toJSON();

expect(tree).toMatchSnapshot();
});

0 comments on commit ed60fae

Please sign in to comment.