Skip to content

Commit e5cd6fb

Browse files
bmigirlTrancever
authored andcommitted
feat: add RadioButton.Item to enable pressing the whole row (#1468)
1 parent c669d51 commit e5cd6fb

File tree

4 files changed

+165
-0
lines changed

4 files changed

+165
-0
lines changed

example/src/ExampleList.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import TextExample from './Examples/TextExample';
3232
import TextInputExample from './Examples/TextInputExample';
3333
import ToggleButtonExample from './Examples/ToggleButtonExample';
3434
import TouchableRippleExample from './Examples/TouchableRippleExample';
35+
import RadioButtonGroupWithItemsExample from './Examples/RadioButtonGroupWithItemsExample';
3536

3637
type Props = {
3738
theme: Theme;
@@ -61,6 +62,7 @@ export const examples: { [key: string]: any } = {
6162
progressbar: ProgressBarExample,
6263
radio: RadioButtonExample,
6364
radioGroup: RadioButtonGroupExample,
65+
radioGroupWithItems: RadioButtonGroupWithItemsExample,
6466
searchbar: SearchbarExample,
6567
snackbar: SnackbarExample,
6668
surface: SurfaceExample,
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import * as React from 'react';
2+
import { View, StyleSheet } from 'react-native';
3+
import { Colors, withTheme, RadioButton, Theme } from 'react-native-paper';
4+
5+
type Props = {
6+
theme: Theme;
7+
};
8+
9+
type State = {
10+
value: string;
11+
};
12+
13+
class RadioButtonGroupWithItemsExample extends React.Component<Props, State> {
14+
static title = 'Radio Button Group With Items';
15+
16+
state = {
17+
value: 'first',
18+
};
19+
20+
render() {
21+
const {
22+
theme: {
23+
colors: { background },
24+
},
25+
} = this.props;
26+
return (
27+
<View
28+
style={[
29+
styles.container,
30+
{
31+
backgroundColor: background,
32+
},
33+
]}
34+
>
35+
<RadioButton.Group
36+
value={this.state.value}
37+
onValueChange={(value: string) => this.setState({ value })}
38+
>
39+
<RadioButton.Item label="First item" value="first" />
40+
<RadioButton.Item label="Second item" value="second" />
41+
</RadioButton.Group>
42+
</View>
43+
);
44+
}
45+
}
46+
47+
const styles = StyleSheet.create({
48+
container: {
49+
flex: 1,
50+
backgroundColor: Colors.white,
51+
padding: 8,
52+
},
53+
});
54+
55+
export default withTheme(RadioButtonGroupWithItemsExample);

src/components/RadioButton.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import RadioButtonAndroid, {
88
// eslint-disable-next-line @typescript-eslint/no-unused-vars
99
RadioButtonAndroid as _RadioButtonAndroid,
1010
} from './RadioButtonAndroid';
11+
import RadioButtonItem from './RadioButtonItem';
1112
import RadioButtonIOS, {
1213
// eslint-disable-next-line @typescript-eslint/no-unused-vars
1314
RadioButtonIOS as _RadioButtonIOS,
@@ -110,6 +111,9 @@ class RadioButton extends React.Component<Props> {
110111
// @component ./RadioButtonIOS.tsx
111112
static IOS = RadioButtonIOS;
112113

114+
// @component = ./RadioButtonItem.tsx
115+
static Item = RadioButtonItem;
116+
113117
handlePress = (context: RadioButtonContextType) => {
114118
const { onPress } = this.props;
115119
const onValueChange = context ? context.onValueChange : () => {};

src/components/RadioButtonItem.tsx

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import * as React from 'react';
2+
import { View, Text, StyleSheet, StyleProp, ViewStyle } from 'react-native';
3+
import TouchableRipple from './TouchableRipple';
4+
import RadioButton from './RadioButton';
5+
import { RadioButtonContext, RadioButtonContextType } from './RadioButtonGroup';
6+
7+
type Props = {
8+
/**
9+
* Value of the radio button.
10+
*/
11+
value: string;
12+
/**
13+
* Label to be displayed on the item.
14+
*/
15+
label: string;
16+
/**
17+
* Function to execute on press.
18+
*/
19+
onPress?: () => void;
20+
/**
21+
* Status of radio button.
22+
*/
23+
status?: 'checked' | 'unchecked';
24+
/**
25+
* Additional styles for container View
26+
*/
27+
style?: StyleProp<ViewStyle>;
28+
};
29+
30+
/**
31+
* RadioButton.Item allows you to press the whole row (item) instead of only the RadioButton.
32+
*
33+
* ## Usage
34+
* ```js
35+
* import * as React from 'react';
36+
* import { View } from 'react-native';
37+
* import { RadioButton, Text } from 'react-native-paper';
38+
*
39+
* export default class MyComponent extends React.Component {
40+
* state = {
41+
* value: 'first',
42+
* };
43+
*
44+
* render() {
45+
* return(
46+
* <RadioButton.Group
47+
* onValueChange={value => this.setState({ value })}
48+
* value={this.state.value}
49+
* >
50+
* <RadioButton.Item label="First item" value="first" />
51+
* <RadioButton.Item label="Second item" value="second" />
52+
* </RadioButton.Group>
53+
* )
54+
* }
55+
* }
56+
*```
57+
*/
58+
class RadioButtonItem extends React.Component<Props> {
59+
static displayName = 'RadioButton.Item';
60+
61+
isChecked = (context: RadioButtonContextType) =>
62+
context.value === this.props.value ? 'checked' : 'unchecked';
63+
64+
handlePress = (context: RadioButtonContextType) => () => {
65+
const { onPress } = this.props;
66+
const onValueChange = context ? context.onValueChange : () => {};
67+
68+
onPress ? onPress() : onValueChange(this.props.value);
69+
};
70+
71+
render() {
72+
const { value, label, style } = this.props;
73+
74+
return (
75+
<RadioButtonContext.Consumer>
76+
{context => (
77+
<TouchableRipple onPress={this.handlePress(context)}>
78+
<View style={[styles.container, style]} pointerEvents="none">
79+
<Text>{label}</Text>
80+
<RadioButton
81+
value={value}
82+
status={
83+
this.props.status || (context && this.isChecked(context))
84+
}
85+
></RadioButton>
86+
</View>
87+
</TouchableRipple>
88+
)}
89+
</RadioButtonContext.Consumer>
90+
);
91+
}
92+
}
93+
94+
export default RadioButtonItem;
95+
96+
const styles = StyleSheet.create({
97+
container: {
98+
flexDirection: 'row',
99+
alignItems: 'center',
100+
justifyContent: 'space-between',
101+
paddingVertical: 8,
102+
paddingHorizontal: 16,
103+
},
104+
});

0 commit comments

Comments
 (0)