diff --git a/src/components/CurrencySymbolButton.tsx b/src/components/CurrencySymbolButton.tsx index 2b736c2ef5275..4d8d3fb4417c8 100644 --- a/src/components/CurrencySymbolButton.tsx +++ b/src/components/CurrencySymbolButton.tsx @@ -38,12 +38,12 @@ function CurrencySymbolButton({onCurrencyButtonPress, currencySymbol, isCurrency src={Expensicons.DownArrow} fill={theme.icon} /> - {currencySymbol} + {currencySymbol} ) : ( - {currencySymbol} + {currencySymbol} ); } diff --git a/src/components/MoneyRequestAmountInput.tsx b/src/components/MoneyRequestAmountInput.tsx index 1b00728fe2cf3..aaeca047757a4 100644 --- a/src/components/MoneyRequestAmountInput.tsx +++ b/src/components/MoneyRequestAmountInput.tsx @@ -96,7 +96,7 @@ type MoneyRequestAmountInputProps = { /** The testID of the input. Used to locate this view in end-to-end tests. */ testID?: string; -} & Pick; +} & Pick; type Selection = { start: number; @@ -136,6 +136,7 @@ function MoneyRequestAmountInput( testID, submitBehavior, shouldApplyPaddingToContainer = false, + shouldUseDefaultLineHeightForPrefix = true, ...props }: MoneyRequestAmountInputProps, forwardedRef: ForwardedRef, @@ -348,6 +349,7 @@ function MoneyRequestAmountInput( testID={testID} submitBehavior={submitBehavior} shouldApplyPaddingToContainer={shouldApplyPaddingToContainer} + shouldUseDefaultLineHeightForPrefix={shouldUseDefaultLineHeightForPrefix} /> ); } diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index ce7167068d63d..97d8961404a2b 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -682,6 +682,7 @@ function MoneyRequestConfirmationList({ maxLength={formattedTotalAmount.length + 1} contentWidth={(formattedTotalAmount.length + 1) * 8} shouldApplyPaddingToContainer + shouldUseDefaultLineHeightForPrefix={false} /> ), })); diff --git a/src/components/SelectionList/SplitListItem.tsx b/src/components/SelectionList/SplitListItem.tsx index 4d1516f090f7d..680545a287dc2 100644 --- a/src/components/SelectionList/SplitListItem.tsx +++ b/src/components/SelectionList/SplitListItem.tsx @@ -143,6 +143,7 @@ function SplitListItem({ maxLength={formattedOriginalAmount.length + 1} contentWidth={(formattedOriginalAmount.length + 1) * 8} shouldApplyPaddingToContainer + shouldUseDefaultLineHeightForPrefix={false} /> diff --git a/src/components/TextInput/BaseTextInput/implementation/index.native.tsx b/src/components/TextInput/BaseTextInput/implementation/index.native.tsx index 119425e57b9f7..c2a221110764f 100644 --- a/src/components/TextInput/BaseTextInput/implementation/index.native.tsx +++ b/src/components/TextInput/BaseTextInput/implementation/index.native.tsx @@ -78,6 +78,7 @@ function BaseTextInput( placeholderTextColor, onClearInput, iconContainerStyle, + shouldUseDefaultLineHeightForPrefix = true, ...props }: BaseTextInputProps, ref: ForwardedRef, @@ -275,6 +276,7 @@ function BaseTextInput( shouldAddPaddingBottom && styles.pb1, ]); + const verticalPaddingDiff = StyleUtils.getVerticalPaddingDiffFromStyle(newTextInputContainerStyles); const inputPaddingLeft = !!prefixCharacter && StyleUtils.getPaddingLeft(prefixCharacterPadding + styles.pl1.paddingLeft); const inputPaddingRight = !!suffixCharacter && StyleUtils.getPaddingRight(StyleUtils.getCharacterPadding(suffixCharacter) + styles.pr1.paddingRight); @@ -300,7 +302,7 @@ function BaseTextInput( variables.componentSizeLarge, typeof maxAutoGrowHeight === 'number' ? maxAutoGrowHeight : 0, ), - isAutoGrowHeightMarkdown && {minHeight: variables.componentSizeLarge}, + isAutoGrowHeightMarkdown && {minHeight: variables.inputHeight}, !isMultiline && styles.componentHeightLarge, touchableInputWrapperStyle, ]} @@ -346,7 +348,7 @@ function BaseTextInput( )} {!!prefixCharacter && ( - + { if (event.nativeEvent.layout.width === 0 && event.nativeEvent.layout.height === 0) { @@ -358,6 +360,7 @@ function BaseTextInput( tabIndex={-1} style={[styles.textInputPrefix, !hasLabel && styles.pv0, styles.pointerEventsNone, prefixStyle]} dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}} + shouldUseDefaultLineHeight={!!shouldUseDefaultLineHeightForPrefix && !shouldApplyHeight} > {prefixCharacter} @@ -431,7 +434,7 @@ function BaseTextInput( )} {((isFocused && !isReadOnly && shouldShowClearButton) || !shouldHideClearButton) && !!value && ( { setValue(''); onClearInput?.(); @@ -443,9 +446,8 @@ function BaseTextInput( size="small" color={theme.iconSuccessFill} style={[ - StyleUtils.getTextInputIconContainerStyles(hasLabel, false), + StyleUtils.getTextInputIconContainerStyles(hasLabel, false, verticalPaddingDiff), styles.ml1, - styles.justifyContentStart, loadingSpinnerStyle, StyleUtils.getOpacityStyle(inputProps.isLoading ? 1 : 0), ]} @@ -453,7 +455,7 @@ function BaseTextInput( )} {!!inputProps.secureTextEntry && ( { event.preventDefault(); @@ -467,7 +469,13 @@ function BaseTextInput( )} {!inputProps.secureTextEntry && !!icon && ( - + , @@ -280,12 +281,12 @@ function BaseTextInput( shouldAddPaddingBottom && styles.pb1, ]); + const verticalPaddingDiff = StyleUtils.getVerticalPaddingDiffFromStyle(newTextInputContainerStyles); const inputPaddingLeft = !!prefixCharacter && StyleUtils.getPaddingLeft(prefixCharacterPadding + styles.pl1.paddingLeft); const inputPaddingRight = !!suffixCharacter && StyleUtils.getPaddingRight(StyleUtils.getCharacterPadding(suffixCharacter) + styles.pr1.paddingRight); // This is workaround for https://github.com/Expensify/App/issues/47939: in case when user is using Chrome on Android we set inputMode to 'search' to disable autocomplete bar above the keyboard. // If we need some other inputMode (eg. 'decimal'), then the autocomplete bar will show, but we can do nothing about it as it's a known Chrome bug. const inputMode = inputProps.inputMode ?? (isMobileChrome() ? 'search' : undefined); - return ( <> {prefixCharacter} @@ -453,7 +454,7 @@ function BaseTextInput( }} > { setValue(''); onClearInput?.(); @@ -466,9 +467,8 @@ function BaseTextInput( size="small" color={theme.iconSuccessFill} style={[ - StyleUtils.getTextInputIconContainerStyles(hasLabel, false), + StyleUtils.getTextInputIconContainerStyles(hasLabel, false, verticalPaddingDiff), styles.ml1, - styles.justifyContentStart, loadingSpinnerStyle, StyleUtils.getOpacityStyle(inputProps.isLoading ? 1 : 0), ]} @@ -476,7 +476,7 @@ function BaseTextInput( )} {!!inputProps.secureTextEntry && ( { e.preventDefault(); @@ -490,7 +490,13 @@ function BaseTextInput( )} {!inputProps.secureTextEntry && !!icon && ( - + ; +} & Pick; type TextInputWithCurrencySymbolProps = Omit & { onSelectionChange?: (start: number, end: number) => void; diff --git a/src/pages/workspace/taxes/ValuePage.tsx b/src/pages/workspace/taxes/ValuePage.tsx index 1120750ec4f06..17e3a3b312a80 100644 --- a/src/pages/workspace/taxes/ValuePage.tsx +++ b/src/pages/workspace/taxes/ValuePage.tsx @@ -95,7 +95,7 @@ function ValuePage({ extraDecimals={CONST.MAX_TAX_RATE_DECIMAL_PLACES - 2} // We increase the amount max length to support the extra decimals. amountMaxLength={CONST.MAX_TAX_RATE_INTEGER_PLACES} - extraSymbol={%} + extraSymbol={%} ref={inputCallbackRef} autoGrowExtraSpace={variables.w80} autoGrowMarginSide="left" diff --git a/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx b/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx index 384f75cc55a1f..f9f772f47cf83 100644 --- a/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx +++ b/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx @@ -117,7 +117,7 @@ function WorkspaceCreateTaxPage({ extraDecimals={CONST.MAX_TAX_RATE_DECIMAL_PLACES - 2} // We increase the amount max length to support the extra decimals. amountMaxLength={CONST.MAX_TAX_RATE_INTEGER_PLACES} - extraSymbol={%} + extraSymbol={%} autoGrowExtraSpace={variables.w80} autoGrowMarginSide="left" style={[styles.iouAmountTextInput, styles.textAlignRight]} diff --git a/src/styles/index.ts b/src/styles/index.ts index d4cb7375a057d..8172058c5a0f9 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -1317,8 +1317,8 @@ const styles = (theme: ThemeColors) => fontSize: variables.fontSizeNormal, lineHeight: variables.lineHeightXLarge, color: theme.text, - paddingTop: 15, - paddingBottom: 8, + paddingTop: variables.inputPaddingTop, + paddingBottom: variables.inputPaddingBottom, paddingLeft: 0, borderWidth: 0, }, @@ -1329,7 +1329,7 @@ const styles = (theme: ThemeColors) => textInputMultilineContainer: { height: '100%', - paddingTop: 15, + paddingTop: variables.inputPaddingTop, }, textInputAndIconContainer: (isMarkdownEnabled: boolean) => { @@ -1378,8 +1378,8 @@ const styles = (theme: ThemeColors) => display: 'flex', flexDirection: 'row', alignItems: 'center', - paddingTop: 15, - paddingBottom: 8, + paddingTop: variables.inputPaddingTop, + paddingBottom: variables.inputPaddingBottom, height: '100%', }, @@ -1390,8 +1390,8 @@ const styles = (theme: ThemeColors) => display: 'flex', flexDirection: 'row', alignItems: 'center', - paddingTop: 15, - paddingBottom: 8, + paddingTop: variables.inputPaddingTop, + paddingBottom: variables.inputPaddingBottom, }, textInputPrefix: { diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts index cfcb31d022744..1cec935f323e7 100644 --- a/src/styles/utils/index.ts +++ b/src/styles/utils/index.ts @@ -1,5 +1,6 @@ import {StyleSheet} from 'react-native'; -import type {AnimatableNumericValue, ColorValue, ImageStyle, PressableStateCallbackType, StyleProp, TextStyle, ViewStyle} from 'react-native'; +// eslint-disable-next-line no-restricted-imports +import type {AnimatableNumericValue, Animated, ColorValue, ImageStyle, PressableStateCallbackType, StyleProp, TextStyle, ViewStyle} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import type {EdgeInsets} from 'react-native-safe-area-context'; import type {ValueOf} from 'type-fest'; @@ -727,6 +728,22 @@ function getPaddingBottom(paddingBottom: number): ViewStyle { }; } +/** + * Get vertical padding diff from provided styles (paddingTop - paddingBottom) + */ +function getVerticalPaddingDiffFromStyle(textInputContainerStyles: ViewStyle): number { + const flatStyle = StyleSheet.flatten(textInputContainerStyles); + + // Safely extract padding values only if they are numbers + const getNumericPadding = (paddingValue: string | number | Animated.AnimatedNode | null | undefined): number => { + return typeof paddingValue === 'number' ? paddingValue : 0; + }; + + const paddingTop = getNumericPadding(flatStyle?.paddingTop ?? flatStyle.padding); + const paddingBottom = getNumericPadding(flatStyle?.paddingBottom ?? flatStyle.padding); + return paddingTop - paddingBottom; +} + /** * Checks to see if the iOS device has safe areas or not */ @@ -1237,6 +1254,7 @@ const staticStyleUtils = { getPaddingLeft, getPaddingRight, getPaddingBottom, + getVerticalPaddingDiffFromStyle, hasSafeAreas, getHeight, getMinimumHeight, @@ -1379,13 +1397,15 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({ /** * Computes styles for the text input icon container. - * Applies horizontal padding if requested, and sets the top margin based on the presence of a label. + * Applies horizontal padding if requested, and sets the top margin based on padding difference. */ - getTextInputIconContainerStyles: (hasLabel: boolean, includePadding = true) => { + getTextInputIconContainerStyles: (hasLabel: boolean, includePadding = true, verticalPaddingDiff = 0): ViewStyle => { const paddingStyle = includePadding ? {paddingHorizontal: 11} : {}; return { ...paddingStyle, - marginTop: hasLabel ? 8 : 16, + marginTop: -(verticalPaddingDiff / 2), + height: '100%', + justifyContent: 'center', }; }, diff --git a/src/styles/variables.ts b/src/styles/variables.ts index d914ff4efe335..cbec992f81045 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -122,7 +122,11 @@ export default { lineHeighTaskTitle: getValueUsingPixelRatio(26, 30), lineHeightSignInHeroXSmall: getValueUsingPixelRatio(32, 37), inputHeight: getValueUsingPixelRatio(52, 72), + inputPaddingTop: getValueUsingPixelRatio(15, 21), + inputPaddingBottom: getValueUsingPixelRatio(8, 11), inputHeightSmall: 28, + inputIconMarginTopSmall: getValueUsingPixelRatio(8, 11), + inputIconMarginTopLarge: getValueUsingPixelRatio(16, 21), formErrorLineHeight: getValueUsingPixelRatio(18, 23), communicationsLinkHeight: getValueUsingPixelRatio(20, 30), alternateTextHeight: getValueUsingPixelRatio(20, 24),