Skip to content

Commit f2151e1

Browse files
authored
TextField - new features: helperText and validationIcon (#3097)
* TextField - new features: helperText and validationIcon * add icon and remove const * fix example and att top margins * fix example * remove redundent
1 parent a978dfd commit f2151e1

File tree

10 files changed

+44
-9
lines changed

10 files changed

+44
-9
lines changed
479 Bytes
Loading
652 Bytes
Loading
831 Bytes
Loading
1.25 KB
Loading
1.77 KB
Loading

demo/src/screens/componentScreens/TextFieldScreen.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
import Assets from '../../assets/Assets';
1717
const {KeyboardAwareInsetsView} = Keyboard;
1818
const priceFormatter = Intl.NumberFormat('en-US');
19+
const validationIcon = require('../../assets/icons/exclamationFillSmall.png');
1920

2021
export default class TextFieldScreen extends Component {
2122
input = React.createRef<TextFieldRef>();
@@ -199,9 +200,11 @@ export default class TextFieldScreen extends Component {
199200
label="Name"
200201
placeholder="Enter full name"
201202
validate="required"
202-
validationMessage="This field is required"
203-
containerStyle={{flexGrow: 1}}
203+
validationMessage="This field is required. That means you have to enter some value"
204+
containerStyle={{flex: 1}}
204205
validationMessagePosition={errorPosition}
206+
helperText={'Enter first and last name'}
207+
validationIcon={validationIcon}
205208
/>
206209
<Button
207210
outline
@@ -351,7 +354,7 @@ export default class TextFieldScreen extends Component {
351354
renderHintExample() {
352355
return (
353356
<>
354-
<Text h3>
357+
<Text h3 marginT-s4>
355358
Hint
356359
</Text>
357360

src/components/textField/ValidationMessage.tsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import React, {useContext, useMemo} from 'react';
22
import {StyleSheet} from 'react-native';
3+
import {Colors} from '../../style';
4+
import View from '../view';
35
import Text from '../text';
6+
import Icon from '../icon';
47
import FieldContext from './FieldContext';
58
import {getRelevantValidationMessage} from './Presenter';
69
import {ValidationMessageProps} from './types';
710

811
const ValidationMessage = ({
912
validationMessage,
13+
validationIcon,
1014
enableErrors,
1115
validationMessageStyle,
1216
retainValidationSpace,
@@ -24,11 +28,24 @@ const ValidationMessage = ({
2428
const relevantValidationMessage = getRelevantValidationMessage(validationMessage, context.failingValidatorIndex);
2529
const showValidationMessage = !context.isValid || (!validate && !!validationMessage);
2630

27-
return (
28-
<Text testID={testID} $textDangerLight style={style}>
29-
{showValidationMessage ? relevantValidationMessage : ''}
30-
</Text>
31-
);
31+
const renderMessage = () => {
32+
return (
33+
<Text testID={testID} $textDangerLight style={style}>
34+
{showValidationMessage ? relevantValidationMessage : ''}
35+
</Text>
36+
);
37+
};
38+
39+
if (validationIcon) {
40+
return (
41+
<View row>
42+
<Icon source={validationIcon} tintColor={Colors.$textDangerLight} size={14} marginR-s1 marginT-1/>
43+
{renderMessage()}
44+
</View>
45+
);
46+
}
47+
48+
return renderMessage();
3249
};
3350

3451
const styles = StyleSheet.create({

src/components/textField/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ const TextField = (props: InternalTextFieldProps) => {
6161
floatOnFocus,
6262
placeholderTextColor,
6363
hint,
64+
helperText,
65+
validationIcon,
6466
// Label
6567
label,
6668
labelColor,
@@ -74,7 +76,7 @@ const TextField = (props: InternalTextFieldProps) => {
7476
enableErrors, // TODO: rename to enableValidation
7577
validationMessageStyle,
7678
validationMessagePosition = ValidationMessagePosition.BOTTOM,
77-
retainValidationSpace = true,
79+
retainValidationSpace = !helperText,
7880
// Char Counter
7981
showCharCounter,
8082
charCounterStyle,
@@ -206,6 +208,7 @@ const TextField = (props: InternalTextFieldProps) => {
206208
enableErrors={enableErrors}
207209
validate={others.validate}
208210
validationMessage={others.validationMessage}
211+
validationIcon={validationIcon}
209212
validationMessageStyle={_validationMessageStyle}
210213
retainValidationSpace={retainValidationSpace}
211214
testID={`${props.testID}.validationMessage`}
@@ -220,6 +223,7 @@ const TextField = (props: InternalTextFieldProps) => {
220223
/>
221224
)}
222225
</View>
226+
<Text $textNeutralHeavy subtext marginT-s1>{helperText}</Text>
223227
</View>
224228
</FieldContext.Provider>
225229
);

src/components/textField/textField.api.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
{"name": "labelStyle", "type": "TextStyle", "description": "Custom style for the field label"},
2121
{"name": "labelProps", "type": "TextProps", "description": "Pass extra props to the label Text element"},
2222
{"name": "hint", "type": "string", "description": "A hint text to display when focusing the field"},
23+
{"name": "helperText", "type": "string", "description": "Text to display under the input"},
2324
{"name": "placeholder", "type": "string", "description": "The placeholder for the field"},
2425
{"name": "placeholderTextColor", "type": "ColorType", "description": "Placeholder text color"},
2526
{"name": "floatingPlaceholder", "type": "boolean", "description": "Pass to add floating placeholder support"},
@@ -47,6 +48,7 @@
4748
"type": "string | string[]",
4849
"description": "The validation message to display when field is invalid (depends on validate)"
4950
},
51+
{"name": "validationIcon", "type": "ImageProps['source']", "description": "Icon left to the validation message"},
5052
{
5153
"name": "validationMessagePosition",
5254
"type": "ValidationMessagePosition",

src/components/textField/types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {TextProps} from '../text';
1212
import {RecorderProps} from '../../typings/recorderTypes';
1313
import {PropsWithChildren, ReactElement} from 'react';
1414
import {ViewProps} from '../view';
15+
import type {ImageProps} from '../image';
1516

1617
export type ColorType =
1718
| string
@@ -125,6 +126,10 @@ export interface ValidationMessageProps {
125126
* Custom style for the validation message
126127
*/
127128
validationMessageStyle?: StyleProp<TextStyle>;
129+
/**
130+
* Icon left to the validation message
131+
*/
132+
validationIcon?: ImageProps['source'];
128133
/**
129134
* Keep the validation space even if there is no validation message
130135
*/
@@ -200,6 +205,10 @@ export type TextFieldProps = MarginModifiers &
200205
* Pass to render a bottom element below the input
201206
*/
202207
bottomAccessory?: ReactElement;
208+
/**
209+
* Text to display under the input
210+
*/
211+
helperText?: string;
203212
/**
204213
* Pass to add floating placeholder support
205214
*/

0 commit comments

Comments
 (0)