Skip to content

Commit

Permalink
fix(text-input): very long input label truncated when scaled (#4414)
Browse files Browse the repository at this point in the history
  • Loading branch information
seb-zabielski authored Jul 27, 2024
1 parent eebc77f commit 1a82b2c
Show file tree
Hide file tree
Showing 6 changed files with 1,080 additions and 814 deletions.
124 changes: 73 additions & 51 deletions src/components/TextInput/Label/InputLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Platform,
StyleSheet,
useWindowDimensions,
View,
} from 'react-native';

import AnimatedText from '../../Typography/AnimatedText';
Expand Down Expand Up @@ -48,6 +49,7 @@ const InputLabel = (props: InputLabelProps) => {
testID,
isV3,
inputContainerLayout,
scaledLabel,
} = props;

const { INPUT_PADDING_HORIZONTAL } = getConstants(isV3);
Expand Down Expand Up @@ -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 || {},
Expand All @@ -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
<Animated.View
<View
pointerEvents="none"
style={[
StyleSheet.absoluteFill,
styles.labelContainer,
Platform.OS !== 'web' && { width },
{ opacity },
labelTranslationX,
]}
style={[StyleSheet.absoluteFill, styles.overflow]}
>
{labelBackground?.({
labeled,
labelLayoutWidth,
labelStyle,
placeholderStyle,
baseLabelTranslateX,
topPosition,
label,
backgroundColor,
roundness,
maxFontSizeMultiplier: maxFontSizeMultiplier,
testID,
})}
<AnimatedText
variant="bodySmall"
onLayout={onLayoutAnimatedText}
onTextLayout={onLabelTextLayout}
<Animated.View
pointerEvents="none"
style={[
commonStyles,
{
color: activeColor,
},
StyleSheet.absoluteFill,
styles.labelContainer,
Platform.OS !== 'web' && { width },
{ opacity },
labelTranslationX,
]}
numberOfLines={1}
maxFontSizeMultiplier={maxFontSizeMultiplier}
testID={`${testID}-label-active`}
>
{label}
</AnimatedText>
<AnimatedText
variant={focused ? 'bodyLarge' : 'bodySmall'}
style={[
commonStyles,
{
color: textColor,
opacity: placeholderOpacity,
},
]}
numberOfLines={1}
maxFontSizeMultiplier={maxFontSizeMultiplier}
testID={`${testID}-label-inactive`}
>
{label}
</AnimatedText>
</Animated.View>
<View
style={{
width: labelWidth,
}}
>
{labelBackground?.({
labeled,
labelLayoutWidth,
labelStyle,
placeholderStyle,
baseLabelTranslateX,
topPosition,
label,
backgroundColor,
roundness,
maxFontSizeMultiplier: maxFontSizeMultiplier,
testID,
})}
<AnimatedText
variant="bodySmall"
onLayout={onLayoutAnimatedText}
onTextLayout={onLabelTextLayout}
style={[
commonStyles,
{
color: activeColor,
},
]}
numberOfLines={1}
maxFontSizeMultiplier={maxFontSizeMultiplier}
testID={`${testID}-label-active`}
>
{label}
</AnimatedText>
<AnimatedText
variant={focused ? 'bodyLarge' : 'bodySmall'}
style={[
commonStyles,
{
color: textColor,
opacity: placeholderOpacity,
},
]}
numberOfLines={1}
maxFontSizeMultiplier={maxFontSizeMultiplier}
testID={`${testID}-label-inactive`}
>
{label}
</AnimatedText>
</View>
</Animated.View>
</View>
);
};

const styles = StyleSheet.create({
overflow: {
overflow: 'hidden',
},
labelContainer: {
zIndex: 3,
},
Expand Down
4 changes: 4 additions & 0 deletions src/components/TextInput/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,8 @@ const TextInput = forwardRef<TextInputHandles, Props>(

const { maxFontSizeMultiplier = 1.5 } = rest;

const scaledLabel = !!(value || focused);

if (mode === 'outlined') {
return (
<TextInputOutlined
Expand Down Expand Up @@ -520,6 +522,7 @@ const TextInput = forwardRef<TextInputHandles, Props>(
onRightAffixLayoutChange={onRightAffixLayoutChange}
maxFontSizeMultiplier={maxFontSizeMultiplier}
contentStyle={contentStyle}
scaledLabel={scaledLabel}
/>
);
}
Expand Down Expand Up @@ -561,6 +564,7 @@ const TextInput = forwardRef<TextInputHandles, Props>(
onRightAffixLayoutChange={onRightAffixLayoutChange}
maxFontSizeMultiplier={maxFontSizeMultiplier}
contentStyle={contentStyle}
scaledLabel={scaledLabel}
/>
);
}
Expand Down
2 changes: 2 additions & 0 deletions src/components/TextInput/TextInputFlat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const TextInputFlat = ({
placeholderTextColor,
testID = 'text-input-flat',
contentStyle,
scaledLabel,
...rest
}: ChildTextInputProps) => {
const isAndroid = Platform.OS === 'android';
Expand Down Expand Up @@ -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}
Expand Down
2 changes: 2 additions & 0 deletions src/components/TextInput/TextInputOutlined.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const TextInputOutlined = ({
placeholderTextColor,
testID = 'text-input-outlined',
contentStyle,
scaledLabel,
...rest
}: ChildTextInputProps) => {
const adornmentConfig = getAdornmentConfig({ left, right });
Expand Down Expand Up @@ -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}
Expand Down
2 changes: 2 additions & 0 deletions src/components/TextInput/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type TextInputProps = React.ComponentPropsWithRef<typeof NativeTextInput> & {
contentStyle?: StyleProp<TextStyle>;
outlineStyle?: StyleProp<ViewStyle>;
underlineStyle?: StyleProp<ViewStyle>;
scaledLabel?: boolean;
};

export type RenderProps = {
Expand Down Expand Up @@ -140,6 +141,7 @@ export type InputLabelProps = {
labelBackground?: any;
maxFontSizeMultiplier?: number | undefined | null;
isV3?: boolean;
scaledLabel?: boolean;
} & LabelProps;

export type LabelBackgroundProps = {
Expand Down
Loading

0 comments on commit 1a82b2c

Please sign in to comment.