Skip to content

Commit

Permalink
fix: set input min width (#3941)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukewalczak authored Sep 18, 2023
1 parent 36ce39b commit 761e3cb
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 4 deletions.
64 changes: 64 additions & 0 deletions example/src/Examples/TextInputExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,57 @@ const TextInputExample = () => {
/>
</View>
) : null}
<View style={styles.row}>
<TextInput
mode="outlined"
label="CVV"
placeholder="CVV"
keyboardType="phone-pad"
maxLength={3}
/>
</View>
<View style={styles.row}>
<TextInput
mode="flat"
label="CVV"
placeholder="CVV"
keyboardType="phone-pad"
maxLength={3}
/>
</View>
<View style={styles.row}>
<TextInput
mode="outlined"
label="Code"
placeholder="Code"
keyboardType="phone-pad"
maxLength={4}
/>
</View>
<View style={styles.row}>
<TextInput
mode="flat"
label="Code"
placeholder="Code"
keyboardType="phone-pad"
maxLength={4}
/>
</View>
<View style={styles.row}>
<TextInput
mode="flat"
label="Month"
placeholder="Month"
style={styles.month}
/>
<TextInput
mode="flat"
label="Year"
placeholder="Year"
keyboardType="phone-pad"
style={styles.year}
/>
</View>
</List.Accordion>
</List.AccordionGroup>
</ScreenWrapper>
Expand Down Expand Up @@ -745,6 +796,19 @@ const styles = StyleSheet.create({
fixedHeight: {
height: 100,
},
row: {
margin: 8,
justifyContent: 'space-between',
flexDirection: 'row',
},
month: {
flex: 1,
marginRight: 4,
},
year: {
flex: 1,
marginLeft: 4,
},
});

export default TextInputExample;
8 changes: 6 additions & 2 deletions src/components/TextInput/Label/InputLabel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Animated, StyleSheet } from 'react-native';
import { Animated, StyleSheet, Dimensions } from 'react-native';

import AnimatedText from '../../Typography/AnimatedText';
import type { InputLabelProps } from '../types';
Expand All @@ -16,6 +16,7 @@ const InputLabel = (props: InputLabelProps) => {
label,
labelError,
onLayoutAnimatedText,
onLabelTextLayout,
hasActiveOutline,
activeColor,
placeholderStyle,
Expand All @@ -40,6 +41,8 @@ const InputLabel = (props: InputLabelProps) => {
testID,
} = props;

const { width } = Dimensions.get('window');

const paddingOffset =
paddingLeft && paddingRight ? { paddingLeft, paddingRight } : {};

Expand Down Expand Up @@ -107,7 +110,7 @@ const InputLabel = (props: InputLabelProps) => {
style={[
StyleSheet.absoluteFill,
styles.labelContainer,
{ opacity },
{ opacity, width },
labelTranslationX,
]}
>
Expand All @@ -127,6 +130,7 @@ const InputLabel = (props: InputLabelProps) => {
<AnimatedText
variant="bodySmall"
onLayout={onLayoutAnimatedText}
onTextLayout={onLabelTextLayout}
style={[
placeholderStyle,
{
Expand Down
22 changes: 22 additions & 0 deletions src/components/TextInput/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
TextInput as NativeTextInput,
TextStyle,
ViewStyle,
NativeSyntheticEvent,
TextLayoutEventData,
} from 'react-native';

import TextInputAffix, {
Expand Down Expand Up @@ -248,6 +250,10 @@ const TextInput = forwardRef<TextInputHandles, Props>(
// Use value from props instead of local state when input is controlled
const value = isControlled ? rest.value : uncontrolledValue;

const [labelTextLayout, setLabelTextLayout] = React.useState({
width: 33,
});

const [labelLayout, setLabelLayout] = React.useState<{
measured: boolean;
width: number;
Expand Down Expand Up @@ -447,6 +453,18 @@ const TextInput = forwardRef<TextInputHandles, Props>(
[labelLayout.height, labelLayout.width]
);

const handleLabelTextLayout = React.useCallback(
({ nativeEvent }: NativeSyntheticEvent<TextLayoutEventData>) => {
setLabelTextLayout({
width: nativeEvent.lines.reduce(
(acc, line) => acc + Math.ceil(line.width),
0
),
});
},
[]
);

const forceFocus = React.useCallback(() => root.current?.focus(), []);

const { maxFontSizeMultiplier = 1.5 } = rest;
Expand All @@ -469,6 +487,7 @@ const TextInput = forwardRef<TextInputHandles, Props>(
focused,
placeholder,
value,
labelTextLayout,
labelLayout,
leftLayout,
rightLayout,
Expand All @@ -481,6 +500,7 @@ const TextInput = forwardRef<TextInputHandles, Props>(
onBlur={handleBlur}
onChangeText={handleChangeText}
onLayoutAnimatedText={handleLayoutAnimatedText}
onLabelTextLayout={handleLabelTextLayout}
onLeftAffixLayoutChange={onLeftAffixLayoutChange}
onRightAffixLayoutChange={onRightAffixLayoutChange}
maxFontSizeMultiplier={maxFontSizeMultiplier}
Expand All @@ -506,6 +526,7 @@ const TextInput = forwardRef<TextInputHandles, Props>(
focused,
placeholder,
value,
labelTextLayout,
labelLayout,
leftLayout,
rightLayout,
Expand All @@ -518,6 +539,7 @@ const TextInput = forwardRef<TextInputHandles, Props>(
onBlur={handleBlur}
onChangeText={handleChangeText}
onLayoutAnimatedText={handleLayoutAnimatedText}
onLabelTextLayout={handleLabelTextLayout}
onLeftAffixLayoutChange={onLeftAffixLayoutChange}
onRightAffixLayoutChange={onRightAffixLayoutChange}
maxFontSizeMultiplier={maxFontSizeMultiplier}
Expand Down
4 changes: 4 additions & 0 deletions src/components/TextInput/TextInputFlat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const TextInputFlat = ({
onBlur,
onChangeText,
onLayoutAnimatedText,
onLabelTextLayout,
onLeftAffixLayoutChange,
onRightAffixLayoutChange,
left,
Expand Down Expand Up @@ -254,6 +255,7 @@ const TextInputFlat = ({
const labelProps = {
label,
onLayoutAnimatedText,
onLabelTextLayout,
placeholderOpacity,
labelError: error,
placeholderStyle: styles.placeholder,
Expand Down Expand Up @@ -405,6 +407,8 @@ const TextInputFlat = ({
: I18nManager.getConstants().isRTL
? 'right'
: 'left',
minWidth:
parentState.labelTextLayout.width + 2 * FLAT_INPUT_OFFSET,
},
Platform.OS === 'web' && { outline: 'none' },
adornmentStyleAdjustmentForNativeInput,
Expand Down
6 changes: 5 additions & 1 deletion src/components/TextInput/TextInputOutlined.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const TextInputOutlined = ({
onBlur,
onChangeText,
onLayoutAnimatedText,
onLabelTextLayout,
onLeftAffixLayoutChange,
onRightAffixLayoutChange,
left,
Expand Down Expand Up @@ -200,6 +201,7 @@ const TextInputOutlined = ({
const labelProps = {
label,
onLayoutAnimatedText,
onLabelTextLayout,
placeholderOpacity,
labelError: error,
placeholderStyle,
Expand Down Expand Up @@ -376,6 +378,9 @@ const TextInputOutlined = ({
? 'right'
: 'left',
paddingHorizontal: INPUT_PADDING_HORIZONTAL,
minWidth:
parentState.labelTextLayout.width +
2 * INPUT_PADDING_HORIZONTAL,
},
Platform.OS === 'web' && { outline: 'none' },
adornmentStyleAdjustmentForNativeInput,
Expand All @@ -398,7 +403,6 @@ const styles = StyleSheet.create({
},
input: {
margin: 0,
zIndex: 1,
},
inputOutlined: {
paddingTop: 8,
Expand Down
5 changes: 5 additions & 0 deletions src/components/TextInput/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import type {
StyleProp,
ViewProps,
ViewStyle,
NativeSyntheticEvent,
TextLayoutEventData,
} from 'react-native';

import type { $Omit, InternalTheme, ThemeProp } from './../../types';
Expand Down Expand Up @@ -70,6 +72,7 @@ export type State = {
focused: boolean;
placeholder?: string;
value?: string;
labelTextLayout: { width: number };
labelLayout: { measured: boolean; width: number; height: number };
leftLayout: { height: number | null; width: number | null };
rightLayout: { height: number | null; width: number | null };
Expand All @@ -83,6 +86,7 @@ export type ChildTextInputProps = {
forceFocus: () => void;
onChangeText?: (value: string) => void;
onLayoutAnimatedText: (args: any) => void;
onLabelTextLayout: (event: NativeSyntheticEvent<TextLayoutEventData>) => void;
onLeftAffixLayoutChange: (event: LayoutChangeEvent) => void;
onRightAffixLayoutChange: (event: LayoutChangeEvent) => void;
} & $Omit<TextInputTypesWithoutMode, 'theme'> & { theme: InternalTheme };
Expand Down Expand Up @@ -114,6 +118,7 @@ export type LabelProps = {
errorColor?: string;
labelError?: boolean | null;
onLayoutAnimatedText: (args: any) => void;
onLabelTextLayout: (event: NativeSyntheticEvent<TextLayoutEventData>) => void;
roundness: number;
maxFontSizeMultiplier?: number | undefined | null;
testID?: string;
Expand Down
Loading

0 comments on commit 761e3cb

Please sign in to comment.