Skip to content

Commit

Permalink
Merge pull request #3668 from Expensify/marcaaron-stories
Browse files Browse the repository at this point in the history
Clean up Checkboxes
  • Loading branch information
marcaaron authored Jun 23, 2021
2 parents 9c89d8b + 73dd983 commit 2fdb908
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 33 deletions.
30 changes: 6 additions & 24 deletions src/components/Checkbox.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {View, Pressable, Text} from 'react-native';
import {View, Pressable} from 'react-native';
import PropTypes from 'prop-types';
import styles from '../styles/styles';
import Icon from './Icon';
Expand All @@ -11,37 +11,19 @@ const propTypes = {

/** A function that is called when the box/label is pressed */
onPress: PropTypes.func.isRequired,

/** Text that appears next to check box */
label: PropTypes.string,
};

const defaultProps = {
label: undefined,
};

const Checkbox = ({
isChecked,
onPress,
label,
}) => (
<View style={styles.flexRow}>
<Pressable onPress={() => onPress(!isChecked)}>
<View style={[styles.checkboxContainer, isChecked && styles.checkedContainer]}>
<Icon src={Checkmark} fill="white" height={14} width={14} />
</View>
</Pressable>
{label && (
<Pressable onPress={() => onPress(!isChecked)}>
<Text style={[styles.ml2, styles.textP]}>
{label}
</Text>
</Pressable>
)}
</View>
<Pressable onPress={() => onPress(!isChecked)}>
<View style={[styles.checkboxContainer, isChecked && styles.checkedContainer]}>
<Icon src={Checkmark} fill="white" height={14} width={14} />
</View>
</Pressable>
);

Checkbox.defaultProps = defaultProps;
Checkbox.propTypes = propTypes;
Checkbox.displayName = 'Checkbox';

Expand Down
31 changes: 24 additions & 7 deletions src/components/CheckboxWithLabel.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import {View, TouchableOpacity} from 'react-native';
import _ from 'underscore';
import styles from '../styles/styles';
import Checkbox from './Checkbox';
import Text from './Text';

const propTypes = {
/** Component to display for label */
LabelComponent: PropTypes.func.isRequired,

/** Whether the checkbox is checked */
isChecked: PropTypes.bool.isRequired,

Expand All @@ -17,25 +15,39 @@ const propTypes = {

/** 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,
};

const defaultProps = {
style: [],
label: undefined,
LabelComponent: undefined,
};

const CheckboxWithLabel = ({
LabelComponent, isChecked, onPress, style,
LabelComponent, isChecked, onPress, style, label,
}) => {
const defaultStyles = [styles.flexRow, styles.alignItemsCenter];
const wrapperStyles = _.isArray(style) ? [...defaultStyles, ...style] : [...defaultStyles, style];

if (!label && !LabelComponent) {
throw new Error('Must provide at least label or LabelComponent prop');
}

return (
<View style={wrapperStyles}>
<Checkbox
isChecked={isChecked}
onPress={onPress}
onPress={() => onPress(!isChecked)}
label={label}
/>
<TouchableOpacity
onPress={onPress}
onPress={() => onPress(!isChecked)}
style={[
styles.ml2,
styles.pr2,
Expand All @@ -45,7 +57,12 @@ const CheckboxWithLabel = ({
styles.alignItemsCenter,
]}
>
<LabelComponent />
{label && (
<Text style={[styles.ml2, styles.textP]}>
{label}
</Text>
)}
{LabelComponent && (<LabelComponent />)}
</TouchableOpacity>
</View>
);
Expand Down
4 changes: 2 additions & 2 deletions src/pages/settings/Profile/ProfilePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import Avatar from '../../../components/Avatar';
import styles from '../../../styles/styles';
import Text from '../../../components/Text';
import Icon from '../../../components/Icon';
import Checkbox from '../../../components/Checkbox';
import themeColors from '../../../styles/themes/default';
import LoginField from './LoginField';
import {DownArrow, Upload, Trashcan} from '../../../components/Icon/Expensicons';
Expand All @@ -33,6 +32,7 @@ import Button from '../../../components/Button';
import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView';
import FixedFooter from '../../../components/FixedFooter';
import Growl from '../../../libs/Growl';
import CheckboxWithLabel from '../../../components/CheckboxWithLabel';

const propTypes = {
/* Onyx Props */
Expand Down Expand Up @@ -379,7 +379,7 @@ class ProfilePage extends Component {
disabled={this.state.isAutomaticTimezone}
/>
</View>
<Checkbox
<CheckboxWithLabel
label={this.props.translate('profilePage.setMyTimezoneAutomatically')}
isChecked={this.state.isAutomaticTimezone}
onPress={this.setAutomaticTimezone}
Expand Down
23 changes: 23 additions & 0 deletions src/stories/Checkbox.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import Checkbox from '../components/Checkbox';

/**
* We use the Component Story Format for writing stories. Follow the docs here:
*
* https://storybook.js.org/docs/react/writing-stories/introduction#component-story-format
*/
export default {
title: 'Components/Checkbox',
component: Checkbox,
};

// eslint-disable-next-line react/jsx-props-no-spreading
const Template = args => <Checkbox {...args} />;

// Arguments can be passed to the component by binding
// See: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
export const Default = Template.bind({});
Default.args = {
onPress: () => {},
isChecked: true,
};
39 changes: 39 additions & 0 deletions src/stories/CheckboxWithLabel.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import CheckboxWithLabel from '../components/CheckboxWithLabel';
import Text from '../components/Text';
import styles from '../styles/styles';

/**
* We use the Component Story Format for writing stories. Follow the docs here:
*
* https://storybook.js.org/docs/react/writing-stories/introduction#component-story-format
*/
export default {
title: 'Components/CheckboxWithLabel',
component: CheckboxWithLabel,
};

// eslint-disable-next-line react/jsx-props-no-spreading
const Template = args => <CheckboxWithLabel {...args} />;

// Arguments can be passed to the component by binding
// See: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
export const Default = Template.bind({});
export const WithLabelComponent = Template.bind({});
Default.args = {
isChecked: true,
label: 'Plain text label',
onPress: () => {},
};

WithLabelComponent.args = {
isChecked: true,
onPress: () => {},
LabelComponent: () => (
<>
<Text style={[styles.textLarge]}>Test</Text>
<Text style={[styles.textMicroBold]}> Test </Text>
<Text style={[styles.textMicroSupporting]}>Test</Text>
</>
),
};

0 comments on commit 2fdb908

Please sign in to comment.