diff --git a/src/components/CheckboxWithLabel.js b/src/components/CheckboxWithLabel.js
index 8ee5c6712a6e..96f85fb25d91 100644
--- a/src/components/CheckboxWithLabel.js
+++ b/src/components/CheckboxWithLabel.js
@@ -1,11 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import {View, TouchableOpacity} from 'react-native';
-import _ from 'underscore';
import styles from '../styles/styles';
import Checkbox from './Checkbox';
import Text from './Text';
-import InlineErrorText from './InlineErrorText';
+import FormHelpMessage from './FormHelpMessage';
const requiredPropsCheck = (props) => {
if (!props.label && !props.LabelComponent) {
@@ -77,8 +76,6 @@ class CheckboxWithLabel extends React.Component {
this.isChecked = props.value || props.defaultValue || props.isChecked;
this.LabelComponent = props.LabelComponent;
- this.defaultStyles = [styles.flexRow, styles.alignItemsCenter];
- this.wrapperStyles = _.isArray(props.style) ? [...this.defaultStyles, ...props.style] : [...this.defaultStyles, props.style];
this.toggleCheckbox = this.toggleCheckbox.bind(this);
}
@@ -90,8 +87,8 @@ class CheckboxWithLabel extends React.Component {
render() {
return (
- <>
-
+
+
)}
-
- {this.props.errorText}
-
- >
+
+
);
}
}
diff --git a/src/components/FormAlertWrapper.js b/src/components/FormAlertWrapper.js
index 921a76c771fc..ed6c16810485 100644
--- a/src/components/FormAlertWrapper.js
+++ b/src/components/FormAlertWrapper.js
@@ -3,16 +3,14 @@ import {View} from 'react-native';
import PropTypes from 'prop-types';
import React from 'react';
import {withNetwork} from './OnyxProvider';
-import Icon from './Icon';
-import * as Expensicons from './Icon/Expensicons';
import RenderHTML from './RenderHTML';
-import TextLink from './TextLink';
import Text from './Text';
-import colors from '../styles/colors';
+import TextLink from './TextLink';
import compose from '../libs/compose';
import networkPropTypes from './networkPropTypes';
import styles from '../styles/styles';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
+import FormHelpMessage from './FormHelpMessage';
const propTypes = {
/** Wrapped child components */
@@ -52,38 +50,35 @@ const defaultProps = {
//
// This component takes other components as a child prop. It will then render any wrapped components as a function using "render props",
// and passes it a (bool) isOffline parameter. Child components can then use the isOffline variable to determine offline behavior.
-const FormAlertWrapper = props => (
-
- {props.isAlertVisible && (
-
-
-
- {!_.isEmpty(props.message) && props.isMessageHtml && ${props.message}`} />}
-
- {!_.isEmpty(props.message) && !props.isMessageHtml && {props.message}}
-
- {_.isEmpty(props.message) && (
- <>
-
- {`${props.translate('common.please')} `}
-
-
- {props.translate('common.fixTheErrors')}
-
-
- {` ${props.translate('common.inTheFormBeforeContinuing')}.`}
-
- >
- )}
-
-
- )}
- {props.children(props.network.isOffline)}
-
-);
+const FormAlertWrapper = (props) => {
+ let children;
+ if (_.isEmpty(props.message)) {
+ children = (
+
+ {`${props.translate('common.please')} `}
+
+ {props.translate('common.fixTheErrors')}
+
+ {` ${props.translate('common.inTheFormBeforeContinuing')}.`}
+
+ );
+ } else if (props.isMessageHtml) {
+ children = ${props.message}`} />;
+ }
+ return (
+
+ {props.isAlertVisible && (
+
+ {children}
+
+ )}
+ {props.children(props.network.isOffline)}
+
+ );
+};
FormAlertWrapper.propTypes = propTypes;
FormAlertWrapper.defaultProps = defaultProps;
diff --git a/src/components/FormHelpMessage.js b/src/components/FormHelpMessage.js
new file mode 100644
index 000000000000..3a78b279c962
--- /dev/null
+++ b/src/components/FormHelpMessage.js
@@ -0,0 +1,56 @@
+import React from 'react';
+import _ from 'underscore';
+import PropTypes from 'prop-types';
+import {View} from 'react-native';
+import Icon from './Icon';
+import * as Expensicons from './Icon/Expensicons';
+import Text from './Text';
+import colors from '../styles/colors';
+import styles from '../styles/styles';
+import stylePropTypes from '../styles/stylePropTypes';
+
+const propTypes = {
+ /** Error or hint text. Ignored when children is not empty */
+ message: PropTypes.string,
+
+ /** Children to render next to dot indicator */
+ children: PropTypes.node,
+
+ /** Indicates whether to show error or hint */
+ isError: PropTypes.bool,
+
+ /** Container style props */
+ style: stylePropTypes,
+};
+
+const defaultProps = {
+ message: '',
+ children: null,
+ isError: true,
+ style: [],
+};
+
+const FormHelpMessage = (props) => {
+ if (_.isEmpty(props.message) && _.isEmpty(props.children)) {
+ return null;
+ }
+
+ return (
+
+ {props.isError && }
+
+ {props.children || (
+
+ {props.message}
+
+ )}
+
+
+ );
+};
+
+FormHelpMessage.propTypes = propTypes;
+FormHelpMessage.defaultProps = defaultProps;
+FormHelpMessage.displayName = 'FormHelpMessage';
+
+export default FormHelpMessage;
diff --git a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js
index 459e904a0bba..c644db26d153 100755
--- a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js
+++ b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js
@@ -29,7 +29,7 @@ const customHTMLElementModels = {
}),
'muted-text': defaultHTMLElementModels.div.extend({
tagName: 'muted-text',
- mixedUAStyles: styles.mutedTextLabel,
+ mixedUAStyles: {...styles.formError, ...styles.mb0},
}),
comment: defaultHTMLElementModels.div.extend({
tagName: 'comment',
diff --git a/src/components/Picker/index.js b/src/components/Picker/index.js
index 4dc676966827..d9b6c00a2635 100644
--- a/src/components/Picker/index.js
+++ b/src/components/Picker/index.js
@@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
import BasePicker from './BasePicker';
import Text from '../Text';
import styles from '../../styles/styles';
-import InlineErrorText from '../InlineErrorText';
+import FormHelpMessage from '../FormHelpMessage';
const propTypes = {
/** Picker label */
@@ -95,9 +95,7 @@ class Picker extends PureComponent {
onInputChange={this.onInputChange}
/>
-
- {this.props.errorText}
-
+
>
);
}
diff --git a/src/components/RadioButtonWithLabel.js b/src/components/RadioButtonWithLabel.js
index 630981970c2c..7665cb3f9159 100644
--- a/src/components/RadioButtonWithLabel.js
+++ b/src/components/RadioButtonWithLabel.js
@@ -5,7 +5,7 @@ import _ from 'underscore';
import styles from '../styles/styles';
import RadioButton from './RadioButton';
import Text from './Text';
-import InlineErrorText from './InlineErrorText';
+import FormHelpMessage from './FormHelpMessage';
const propTypes = {
/** Whether the radioButton is checked */
@@ -75,9 +75,7 @@ const RadioButtonWithLabel = (props) => {
{LabelComponent && ()}
-
- {props.errorText}
-
+
>
);
};
diff --git a/src/components/TextInput/BaseTextInput.js b/src/components/TextInput/BaseTextInput.js
index 2f970bbb12e4..fe29ff79bf25 100644
--- a/src/components/TextInput/BaseTextInput.js
+++ b/src/components/TextInput/BaseTextInput.js
@@ -18,6 +18,7 @@ import variables from '../../styles/variables';
import Checkbox from '../Checkbox';
import getSecureEntryKeyboardType from '../../libs/getSecureEntryKeyboardType';
import CONST from '../../CONST';
+import FormHelpMessage from '../FormHelpMessage';
class BaseTextInput extends Component {
constructor(props) {
@@ -198,7 +199,6 @@ class BaseTextInput extends Component {
const inputProps = _.omit(this.props, _.keys(baseTextInputPropTypes.propTypes));
const hasLabel = Boolean(this.props.label.length);
const inputHelpText = this.props.errorText || this.props.hint;
- const formHelpStyles = this.props.errorText ? styles.formError : styles.formHelp;
const placeholder = (this.props.prefixCharacter || this.state.isFocused || !hasLabel || (hasLabel && this.props.forceActiveLabel)) ? this.props.placeholder : null;
const textInputContainerStyles = _.reduce([
styles.textInputContainer,
@@ -305,9 +305,7 @@ class BaseTextInput extends Component {
{!_.isEmpty(inputHelpText) && (
-
- {inputHelpText}
-
+
)}
{/*
diff --git a/src/stories/FormAlertWithSubmitButton.stories.js b/src/stories/FormAlertWithSubmitButton.stories.js
index 9747c447cf0d..eb58b7b59322 100644
--- a/src/stories/FormAlertWithSubmitButton.stories.js
+++ b/src/stories/FormAlertWithSubmitButton.stories.js
@@ -17,7 +17,9 @@ const Template = args => ;
// Arguments can be passed to the component by binding
// See: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Default = Template.bind({});
-Default.args = {
+const HtmlError = Template.bind({});
+
+const defaultArgs = {
isAlertVisible: true,
onSubmit: () => {},
buttonText: 'Submit',
@@ -26,7 +28,12 @@ Default.args = {
},
};
+Default.args = defaultArgs;
+const html = 'This is a test. None of
these strings
should display as HTML
.';
+HtmlError.args = {...defaultArgs, isMessageHtml: true, message: html};
+
export default story;
export {
Default,
+ HtmlError,
};