From b83fa8dccdc26d35c1c9335e2003425676e6a8f7 Mon Sep 17 00:00:00 2001 From: Avilash Date: Sun, 11 Oct 2026 01:12:35 +0530 Subject: [PATCH] fix(text-input): apply flexShrink to root container to avoid parent blowout (#4790) --- src/components/TextInput/TextInput.tsx | 19 ++++++------ src/components/TextInput/styles.ts | 3 ++ src/components/__tests__/TextInput.test.tsx | 15 ++++++++++ .../__snapshots__/TextInput.test.tsx.snap | 30 +++++++++++++++++++ 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/components/TextInput/TextInput.tsx b/src/components/TextInput/TextInput.tsx index b89e2b35d4..2aa712cece 100644 --- a/src/components/TextInput/TextInput.tsx +++ b/src/components/TextInput/TextInput.tsx @@ -125,8 +125,7 @@ export type OutlinedTextInputHookData = SharedTextInputStyleData & { }; export type TextInputLayoutData = - | FilledTextInputHookData - | OutlinedTextInputHookData; + FilledTextInputHookData | OutlinedTextInputHookData; export type TextInputLayoutState = Omit< TextInputLayoutData, @@ -145,8 +144,7 @@ export type TextInputHookReturn = SharedTextInputStyleData & { selectionColor: ColorValue; cursorColor: ColorValue; animatedActiveOutlineStyles: - | StyleProp>> - | undefined; + StyleProp>> | undefined; animatedContainerStyle: StyleProp>>; animatedLabelWrapperStyles: StyleProp>>; containerStyles: StyleProp; @@ -158,11 +156,9 @@ export type TextInputHookReturn = SharedTextInputStyleData & { counterText: string; accessibilityProps: GetAccessibilityDataReturn; renderLeadingAccessory: - | ((props: TextInputAccessoryProps) => React.ReactNode) - | undefined; + ((props: TextInputAccessoryProps) => React.ReactNode) | undefined; renderTrailingAccessory: - | ((props: TextInputAccessoryProps) => React.ReactNode) - | undefined; + ((props: TextInputAccessoryProps) => React.ReactNode) | undefined; onChangeText: (text: string) => void; onFocus: (e: FocusEvent) => void; onBlur: (e: BlurEvent) => void; @@ -360,7 +356,12 @@ function TextInput({ }); return ( - + {/* Disabled tint overlay — filled variant only. A childless absolutely-positioned View whose translucent fill is applied via the diff --git a/src/components/TextInput/styles.ts b/src/components/TextInput/styles.ts index 0a65662a5a..0022c79da0 100644 --- a/src/components/TextInput/styles.ts +++ b/src/components/TextInput/styles.ts @@ -17,6 +17,9 @@ import { tokens } from '../../theme/tokens'; const { bodyLarge, bodySmall } = tokens.md.sys.typescale; export const styles = StyleSheet.create({ + root: { + flexShrink: 1, + }, input: { paddingVertical: 0, paddingHorizontal: 0, diff --git a/src/components/__tests__/TextInput.test.tsx b/src/components/__tests__/TextInput.test.tsx index b87e482c7f..9de5f94059 100644 --- a/src/components/__tests__/TextInput.test.tsx +++ b/src/components/__tests__/TextInput.test.tsx @@ -1340,3 +1340,18 @@ it('hides prefix/suffix when blurring after clear() was called while focused', a expect(screen.queryByText('$')).not.toBeOnTheScreen(); expect(screen.queryByText('/100')).not.toBeOnTheScreen(); }); + +it('applies flexShrink: 1 to the outer container to prevent overflowing constrained flex parents', async () => { + const { root } = await render( + + {}} + /> + + ); + + const pressable = getOuterTextInputPressable(root); + expect(pressable).toHaveStyle({ flexShrink: 1 }); +}); diff --git a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap index 6efc467066..fa7c131060 100644 --- a/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/TextInput.test.tsx.snap @@ -32,6 +32,11 @@ exports[`renders filled TextInput with TextInput.Icon accessories 1`] = ` onResponderTerminationRequest={[Function]} onStartShouldSetResponder={[Function]} role="none" + style={ + { + "flexShrink": 1, + } + } >