-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8009 from Expensify/nat-radiobutton
Add RadioButton components
- Loading branch information
Showing
5 changed files
with
202 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import React from 'react'; | ||
import {View, Pressable} from 'react-native'; | ||
import PropTypes from 'prop-types'; | ||
import styles from '../styles/styles'; | ||
import Icon from './Icon'; | ||
import * as Expensicons from './Icon/Expensicons'; | ||
|
||
const propTypes = { | ||
/** Whether radioButton is checked */ | ||
isChecked: PropTypes.bool.isRequired, | ||
|
||
/** A function that is called when the box/label is pressed */ | ||
onPress: PropTypes.func.isRequired, | ||
|
||
/** Should the input be styled for errors */ | ||
hasError: PropTypes.bool, | ||
|
||
/** Should the input be disabled */ | ||
disabled: PropTypes.bool, | ||
}; | ||
|
||
const defaultProps = { | ||
hasError: false, | ||
disabled: false, | ||
}; | ||
|
||
const RadioButton = props => ( | ||
<Pressable | ||
disabled={props.disabled} | ||
onPress={props.onPress} | ||
> | ||
<View | ||
style={[ | ||
styles.radioButtonContainer, | ||
props.isChecked && styles.checkedContainer, | ||
props.hasError && styles.borderColorDanger, | ||
props.disabled && styles.cursorDisabled, | ||
]} | ||
> | ||
<Icon src={Expensicons.Checkmark} fill="white" height={14} width={14} /> | ||
</View> | ||
</Pressable> | ||
); | ||
|
||
RadioButton.propTypes = propTypes; | ||
RadioButton.defaultProps = defaultProps; | ||
RadioButton.displayName = 'RadioButton'; | ||
|
||
export default RadioButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import {View, TouchableOpacity} from 'react-native'; | ||
import _ from 'underscore'; | ||
import styles from '../styles/styles'; | ||
import RadioButton from './RadioButton'; | ||
import Text from './Text'; | ||
import InlineErrorText from './InlineErrorText'; | ||
|
||
const propTypes = { | ||
/** Whether the radioButton is checked */ | ||
isChecked: PropTypes.bool.isRequired, | ||
|
||
/** Called when the radioButton or label is pressed */ | ||
onPress: PropTypes.func.isRequired, | ||
|
||
/** Container styles */ | ||
style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), | ||
|
||
/** Text that appears next to check box */ | ||
label: PropTypes.string, | ||
|
||
/** Component to display for label */ | ||
LabelComponent: PropTypes.func, | ||
|
||
/** Should the input be styled for errors */ | ||
hasError: PropTypes.bool, | ||
|
||
/** Error text to display */ | ||
errorText: PropTypes.string, | ||
}; | ||
|
||
const defaultProps = { | ||
style: [], | ||
label: undefined, | ||
LabelComponent: undefined, | ||
hasError: false, | ||
errorText: '', | ||
}; | ||
|
||
const RadioButtonWithLabel = (props) => { | ||
const LabelComponent = props.LabelComponent; | ||
const defaultStyles = [styles.flexRow, styles.alignItemsCenter]; | ||
const wrapperStyles = _.isArray(props.style) ? [...defaultStyles, ...props.style] : [...defaultStyles, props.style]; | ||
|
||
if (!props.label && !LabelComponent) { | ||
throw new Error('Must provide at least label or LabelComponent prop'); | ||
} | ||
return ( | ||
<> | ||
<View style={wrapperStyles}> | ||
<RadioButton | ||
isChecked={props.isChecked} | ||
onPress={props.onPress} | ||
label={props.label} | ||
hasError={props.hasError} | ||
/> | ||
<TouchableOpacity | ||
onPress={() => props.onPress()} | ||
style={[ | ||
styles.ml3, | ||
styles.pr2, | ||
styles.w100, | ||
styles.flexRow, | ||
styles.flexWrap, | ||
styles.flexShrink1, | ||
styles.alignItemsCenter, | ||
]} | ||
> | ||
{props.label && ( | ||
<Text style={[styles.ml1]}> | ||
{props.label} | ||
</Text> | ||
)} | ||
{LabelComponent && (<LabelComponent />)} | ||
</TouchableOpacity> | ||
</View> | ||
{!_.isEmpty(props.errorText) && ( | ||
<InlineErrorText> | ||
{props.errorText} | ||
</InlineErrorText> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
RadioButtonWithLabel.propTypes = propTypes; | ||
RadioButtonWithLabel.defaultProps = defaultProps; | ||
RadioButtonWithLabel.displayName = 'RadioButtonWithLabel'; | ||
|
||
export default RadioButtonWithLabel; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import React from 'react'; | ||
import {View} from 'react-native'; | ||
import PropTypes from 'prop-types'; | ||
import _ from 'underscore'; | ||
import RadioButtonWithLabel from './RadioButtonWithLabel'; | ||
import styles from '../styles/styles'; | ||
|
||
const propTypes = { | ||
/** List of choices to display via radio buttons */ | ||
items: PropTypes.arrayOf(PropTypes.shape({ | ||
label: PropTypes.string.isRequired, | ||
value: PropTypes.string.isRequired, | ||
})).isRequired, | ||
|
||
/** Callback to fire when selecting a radio button */ | ||
onPress: PropTypes.func.isRequired, | ||
}; | ||
|
||
class RadioButtons extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
|
||
this.state = { | ||
checkedValue: '', | ||
}; | ||
} | ||
|
||
render() { | ||
return ( | ||
<View> | ||
{_.map(this.props.items, item => ( | ||
<RadioButtonWithLabel | ||
isChecked={item.value === this.state.checkedValue} | ||
style={[styles.mt4]} | ||
onPress={() => { | ||
this.setState({checkedValue: item.value}); | ||
return this.props.onPress(item.value); | ||
}} | ||
label={item.label} | ||
/> | ||
))} | ||
</View> | ||
); | ||
} | ||
} | ||
|
||
RadioButtons.propTypes = propTypes; | ||
|
||
export default RadioButtons; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters