Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TextField - new outline preset #3066

Merged
merged 10 commits into from
May 19, 2024
2 changes: 1 addition & 1 deletion demo/src/configurations.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ export const loadDemoConfigurations = () => {
});

/* Components */
TextField.defaultProps = {...TextField.defaultProps, preset: TextField.presets.UNDERLINE};
TextField.defaultProps = {preset: TextField.presets.UNDERLINE, ...TextField.defaultProps};
};
71 changes: 47 additions & 24 deletions demo/src/screens/componentScreens/TextFieldScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default class TextFieldScreen extends Component {
isReadonly: false,
value: 'Initial Value',
isSearching: false,
customPreset: 'underline',
preset: TextField.presets.UNDERLINE,
price: ''
};

Expand All @@ -44,11 +44,17 @@ export default class TextFieldScreen extends Component {
renderPresetExample() {
return (
<>
<Text h3 marginB-s1 marginT-s4>
Underline Preset
</Text>
<View marginV-s3>
<Text h3>
Presets
</Text>
<View row centerV>
<Text marginR-s4 $textPrimary>Preset:</Text>
<SegmentedControl segments={[{label: 'Underline'}, {label: 'Outline'}]} onChangeIndex={this.onChangeIndexFieldStyle}/>
</View>
</View>

<TextField ref={this.input} placeholder="Enter full name"/>
<TextField ref={this.input} placeholder="Enter full name" preset={this.state.preset}/>
</>
);
}
Expand Down Expand Up @@ -175,7 +181,7 @@ export default class TextFieldScreen extends Component {
// validateOnStart
// validateOnBlur
/>
<View row spread center marginV-s3>
<View row spread center>
<TextField
ref={this.inputWithValidation}
label="Name"
Expand Down Expand Up @@ -261,33 +267,50 @@ export default class TextFieldScreen extends Component {
}

onChangeIndexFieldStyle = (index: number) => {
this.setState({customPreset: index === 0 ? 'underline' : 'outline'});
this.setState({preset: index === 0 ? 'underline' : 'outline'});
};

getDynamicFieldStyle = (context, props) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This behavior can be achieved by passing a color object with all states, any reason you are doing it like this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have a prop to control the underline color with the ColorType... What are you referring to?

let color = Colors.$outlineNeutral;

if (context?.isFocused) {
color = Colors.$outlinePrimary;
}
if (context?.hasValue && context?.isValid === false) {
color = Colors.$outlineDanger;
}
if (context?.hasValue && context?.isValid) {
color = Colors.$textSuccess;
}
if (context?.disabled) {
color = Colors.$outlineDefault;
}
if (context?.readonly) {
color = Colors.$outlineDisabled;
}

return props?.preset === TextField.presets.UNDERLINE ? {borderBottomColor: color} : {borderColor: color};
};

renderDynamicFieldExample() {
const {customPreset, isDisabled, isReadonly} = this.state;
const {preset, isDisabled, isReadonly} = this.state;

return (
<>
<View>
<Text h3 marginB-s3>
Dynamic Field Style
</Text>
<View row centerV>
<Text marginR-s4 $textPrimary>Custom style:</Text>
<SegmentedControl segments={[{label: 'Underline'}, {label: 'Outline'}]} onChangeIndex={this.onChangeIndexFieldStyle}/>
</View>
</View>
<Text h3 marginB-s3>
Dynamic Field Style
</Text>

<TextField
label="Label"
placeholder="Enter text..."
preset={customPreset}
dynamicFieldStyle={(_state, {preset}) =>
preset === 'underline' ? styles.underline : styles.outline
}
label="Email"
placeholder="Enter valid email"
validate={'email'}
validateOnChange
validationMessage="Email is invalid"
preset={preset}
editable={!isDisabled}
readonly={isReadonly}
dynamicFieldStyle={this.getDynamicFieldStyle}
/>
</>
);
Expand Down Expand Up @@ -384,10 +407,10 @@ export default class TextFieldScreen extends Component {
{this.renderPresetExample()}
{this.renderPlaceholdersExample()}
{this.renderValidationExample()}
{this.renderStateColorsExample()}
{this.renderHintExample()}
{this.renderCherCounterExample()}
{this.renderAccessoriesExample()}
{this.renderStateColorsExample()}
{this.renderDynamicFieldExample()}
{this.renderFormatterExample()}
{this.renderCustomAlignmentExample()}
Expand Down
3 changes: 2 additions & 1 deletion src/components/textField/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import CharCounter from './CharCounter';

interface StaticMembers {
validationMessagePositions: typeof ValidationMessagePosition;
presets: typeof Presets;
}

/**
Expand Down Expand Up @@ -199,7 +200,7 @@ const TextField = (props: InternalTextFieldProps) => {
{trailingAccessory}
{/* </View> */}
</View>
<View row spread>
<View row spread marginT-s1>
{validationMessagePosition === ValidationMessagePosition.BOTTOM && (
<ValidationMessage
enableErrors={enableErrors}
Expand Down
18 changes: 18 additions & 0 deletions src/components/textField/presets/outline.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {StyleSheet} from 'react-native';
import {BorderRadiuses, Colors, Spacings} from '../../../style';
import underline from './underline';

const styles = StyleSheet.create({
field: {
borderWidth: 1,
borderColor: Colors.$outlineDisabled,
borderRadius: BorderRadiuses.br20,
paddingHorizontal: Spacings.s3,
paddingVertical: Spacings.s2
}
});

export default {
...underline,
fieldStyle: styles.field
};
3 changes: 2 additions & 1 deletion src/components/textField/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ export enum ValidationMessagePosition {

export enum Presets {
DEFAULT = 'default', // TODO: remove
UNDERLINE = 'underline'
UNDERLINE = 'underline',
OUTLINE = 'outline'
}

export type ValidationMessagePositionType = `${ValidationMessagePosition}` | ValidationMessagePosition;
Expand Down
10 changes: 9 additions & 1 deletion src/components/textField/usePreset.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import underlinePreset from './presets/underline';
import outlinePreset from './presets/outline';
import {InternalTextFieldProps, Presets} from './types';

export default function usePreset({preset, ...props}: InternalTextFieldProps) {
let presetConfig;
if (preset === Presets.DEFAULT || preset === Presets.UNDERLINE) {
return {...underlinePreset, ...props, fieldStyle: [underlinePreset.fieldStyle, props.fieldStyle]};
presetConfig = underlinePreset;
} else if (preset === Presets.OUTLINE) {
presetConfig = outlinePreset;
}

if (presetConfig) {
return {...presetConfig, ...props, fieldStyle: [presetConfig.fieldStyle, props.fieldStyle]};
}
return props;
}
2 changes: 1 addition & 1 deletion webDemo/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ const itemsToRender: ItemToRender[] = [
containerStyle={{marginBottom: 10}}
placeholder="Enter your email..."
validationMessage={['Email is required', 'Email is invalid']}
validationMessagePosition={'top'}
validationMessagePosition={'bottom'}
enableErrors
validate={['required', 'email']}
validateOnStart={false}
Expand Down