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

fix(text-input): very long input label truncated when scaled #4414

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading