diff --git a/src/components/TextInput/Label/InputLabel.tsx b/src/components/TextInput/Label/InputLabel.tsx index 9cfe9680f5..eebda816b9 100644 --- a/src/components/TextInput/Label/InputLabel.tsx +++ b/src/components/TextInput/Label/InputLabel.tsx @@ -5,6 +5,7 @@ import { Platform, StyleSheet, useWindowDimensions, + View, } from 'react-native'; import AnimatedText from '../../Typography/AnimatedText'; @@ -48,6 +49,7 @@ const InputLabel = (props: InputLabelProps) => { testID, isV3, inputContainerLayout, + scaledLabel, } = props; const { INPUT_PADDING_HORIZONTAL } = getConstants(isV3); @@ -110,11 +112,17 @@ const InputLabel = (props: InputLabelProps) => { ], }; + const labelWidth = + (inputContainerLayout.width + INPUT_PADDING_HORIZONTAL / 2) / + (scaledLabel ? labelScale : 1); + const commonStyles = [ placeholderStyle, { top: topPosition, - maxWidth: inputContainerLayout.width + INPUT_PADDING_HORIZONTAL / 2, + }, + { + maxWidth: labelWidth, }, labelStyle, paddingOffset || {}, @@ -127,65 +135,79 @@ const InputLabel = (props: InputLabelProps) => { return ( // Position colored placeholder and gray placeholder on top of each other and crossfade them // This gives the effect of animating the color, but allows us to use native driver - - {labelBackground?.({ - labeled, - labelLayoutWidth, - labelStyle, - placeholderStyle, - baseLabelTranslateX, - topPosition, - label, - backgroundColor, - roundness, - maxFontSizeMultiplier: maxFontSizeMultiplier, - testID, - })} - - {label} - - - {label} - - + + {labelBackground?.({ + labeled, + labelLayoutWidth, + labelStyle, + placeholderStyle, + baseLabelTranslateX, + topPosition, + label, + backgroundColor, + roundness, + maxFontSizeMultiplier: maxFontSizeMultiplier, + testID, + })} + + {label} + + + {label} + + + + ); }; const styles = StyleSheet.create({ + overflow: { + overflow: 'hidden', + }, labelContainer: { zIndex: 3, }, diff --git a/src/components/TextInput/TextInput.tsx b/src/components/TextInput/TextInput.tsx index 6b0083ae70..4041699d85 100644 --- a/src/components/TextInput/TextInput.tsx +++ b/src/components/TextInput/TextInput.tsx @@ -482,6 +482,8 @@ const TextInput = forwardRef( const { maxFontSizeMultiplier = 1.5 } = rest; + const scaledLabel = !!(value || focused); + if (mode === 'outlined') { return ( ( onRightAffixLayoutChange={onRightAffixLayoutChange} maxFontSizeMultiplier={maxFontSizeMultiplier} contentStyle={contentStyle} + scaledLabel={scaledLabel} /> ); } @@ -561,6 +564,7 @@ const TextInput = forwardRef( onRightAffixLayoutChange={onRightAffixLayoutChange} maxFontSizeMultiplier={maxFontSizeMultiplier} contentStyle={contentStyle} + scaledLabel={scaledLabel} /> ); } diff --git a/src/components/TextInput/TextInputFlat.tsx b/src/components/TextInput/TextInputFlat.tsx index c9dabcc228..31ae029777 100644 --- a/src/components/TextInput/TextInputFlat.tsx +++ b/src/components/TextInput/TextInputFlat.tsx @@ -74,6 +74,7 @@ const TextInputFlat = ({ placeholderTextColor, testID = 'text-input-flat', contentStyle, + scaledLabel, ...rest }: ChildTextInputProps) => { const isAndroid = Platform.OS === 'android'; @@ -375,6 +376,7 @@ const TextInputFlat = ({ labeled={parentState.labeled} error={parentState.error} focused={parentState.focused} + scaledLabel={scaledLabel} wiggle={Boolean(parentState.value && labelProps.labelError)} labelLayoutMeasured={parentState.labelLayout.measured} labelLayoutWidth={parentState.labelLayout.width} diff --git a/src/components/TextInput/TextInputOutlined.tsx b/src/components/TextInput/TextInputOutlined.tsx index bdecd73569..2f5b2af6bd 100644 --- a/src/components/TextInput/TextInputOutlined.tsx +++ b/src/components/TextInput/TextInputOutlined.tsx @@ -76,6 +76,7 @@ const TextInputOutlined = ({ placeholderTextColor, testID = 'text-input-outlined', contentStyle, + scaledLabel, ...rest }: ChildTextInputProps) => { const adornmentConfig = getAdornmentConfig({ left, right }); @@ -364,6 +365,7 @@ const TextInputOutlined = ({ labeled={parentState.labeled} error={parentState.error} focused={parentState.focused} + scaledLabel={scaledLabel} wiggle={Boolean(parentState.value && labelProps.labelError)} labelLayoutMeasured={parentState.labelLayout.measured} labelLayoutWidth={parentState.labelLayout.width} diff --git a/src/components/TextInput/types.tsx b/src/components/TextInput/types.tsx index 50863082ed..7564a384c8 100644 --- a/src/components/TextInput/types.tsx +++ b/src/components/TextInput/types.tsx @@ -45,6 +45,7 @@ type TextInputProps = React.ComponentPropsWithRef & { contentStyle?: StyleProp; outlineStyle?: StyleProp; underlineStyle?: StyleProp; + scaledLabel?: boolean; }; export type RenderProps = { @@ -140,6 +141,7 @@ export type InputLabelProps = { labelBackground?: any; maxFontSizeMultiplier?: number | undefined | null; isV3?: boolean; + scaledLabel?: boolean; } & LabelProps; export type LabelBackgroundProps = { diff --git a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap index 17d37db5db..e3d23d7f1b 100644 --- a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -48,103 +48,129 @@ exports[`call onPress when affix adornment pressed 1`] = ` } > - - Flat input - - + + Flat input + + - Flat input - + "color": "rgba(73, 69, 79, 1)", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": undefined, + "left": 0, + "letterSpacing": 0.15, + "lineHeight": 19.2, + "maxWidth": 73, + "opacity": 0, + "paddingLeft": 16, + "paddingRight": 16, + "position": "absolute", + "textAlign": "left", + "top": 30, + "transform": [ + { + "translateX": 0, + }, + { + "translateY": 0, + }, + { + "scale": 1, + }, + ], + "writingDirection": "ltr", + } + } + testID="text-input-flat-label-inactive" + > + Flat input + + + - - - Flat input - - - + + Flat input + + + - - Flat input - - + testID="text-input-flat-label-inactive" + > + + Flat input + + + + - - Flat input - - - Flat input - + > + + Flat input + + + Flat input + + + - - Flat input - - + + Flat input + + - Flat input - + "color": "rgba(73, 69, 79, 1)", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": undefined, + "left": 0, + "letterSpacing": 0.15, + "lineHeight": undefined, + "maxWidth": 97.33333333333333, + "opacity": 0, + "paddingLeft": 16, + "paddingRight": 16, + "position": "absolute", + "textAlign": "left", + "top": 30, + "transform": [ + { + "translateX": 0, + }, + { + "translateY": -12, + }, + { + "scale": 0.75, + }, + ], + "writingDirection": "ltr", + } + } + testID="text-input-flat-label-inactive" + > + Flat input + + + - - Outline Input - - + - Outline Input - - + + Outline Input + + + Outline Input + + - Outline Input - + "color": "rgba(73, 69, 79, 1)", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": undefined, + "left": 0, + "letterSpacing": 0.15, + "lineHeight": undefined, + "maxWidth": 97.33333333333333, + "opacity": 0, + "paddingHorizontal": 16, + "position": "absolute", + "textAlign": "left", + "top": 58, + "transform": [ + { + "translateX": 0, + }, + { + "translateY": -52, + }, + { + "scale": 0.75, + }, + ], + "writingDirection": "ltr", + } + } + testID="text-input-outlined-label-inactive" + > + Outline Input + + + - - With padding - - + + With padding + + - With padding - + "color": "rgba(73, 69, 79, 1)", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": undefined, + "left": 0, + "letterSpacing": 0.15, + "lineHeight": undefined, + "maxWidth": 97.33333333333333, + "opacity": 0, + "paddingLeft": 16, + "paddingRight": 16, + "position": "absolute", + "textAlign": "left", + "top": 30, + "transform": [ + { + "translateX": 0, + }, + { + "translateY": -12, + }, + { + "scale": 0.75, + }, + ], + "writingDirection": "ltr", + } + } + testID="text-input-flat-label-inactive" + > + With padding + + + - - Flat input - - + - Flat input - + + + Flat input + + + Flat input + + + - - Flat input - - + + Flat input + + - Flat input - + "color": "rgba(73, 69, 79, 1)", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": undefined, + "left": 0, + "letterSpacing": 0.15, + "lineHeight": undefined, + "maxWidth": 97.33333333333333, + "opacity": 0, + "paddingLeft": 16, + "paddingRight": 56, + "position": "absolute", + "textAlign": "left", + "top": 30, + "transform": [ + { + "translateX": 0, + }, + { + "translateY": -12, + }, + { + "scale": 0.75, + }, + ], + "writingDirection": "ltr", + } + } + testID="text-input-flat-label-inactive" + > + Flat input + + + - - Flat input - - + + Flat input + + - Flat input - + "color": "rgba(73, 69, 79, 1)", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": undefined, + "left": 0, + "letterSpacing": 0.15, + "lineHeight": undefined, + "maxWidth": 97.33333333333333, + "opacity": 0, + "paddingLeft": 56, + "paddingRight": 56, + "position": "absolute", + "textAlign": "left", + "top": 30, + "transform": [ + { + "translateX": 0, + }, + { + "translateY": -12, + }, + { + "scale": 0.75, + }, + ], + "writingDirection": "ltr", + } + } + testID="text-input-flat-label-inactive" + > + Flat input + + +