From c3f83f902816ae9c18cf2f434af5bd02530ae1b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillermo=20Vay=C3=A1?= Date: Tue, 24 Feb 2026 18:17:04 +0100 Subject: [PATCH] [MM-67456] Allow OptionItem labels to wrap to two lines (#9504) --- .../base_option/index.test.tsx | 33 +++++++++++++++++++ .../common_post_options/base_option/index.tsx | 1 + app/components/option_item/index.tsx | 4 ++- .../option_item/option_item.test.tsx | 11 +++++++ .../options/app_bindings_post_option.tsx | 1 + 5 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 app/components/common_post_options/base_option/index.test.tsx diff --git a/app/components/common_post_options/base_option/index.test.tsx b/app/components/common_post_options/base_option/index.test.tsx new file mode 100644 index 000000000..1f555521a --- /dev/null +++ b/app/components/common_post_options/base_option/index.test.tsx @@ -0,0 +1,33 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import OptionItem from '@components/option_item'; +import {renderWithIntlAndTheme} from '@test/intl-test-helper'; + +import BaseOption from './index'; + +jest.mock('@components/option_item'); +jest.mocked(OptionItem).mockImplementation((props) => React.createElement('OptionItem', props)); + +describe('BaseOption', () => { + it('should force single line labels', () => { + renderWithIntlAndTheme( + , + ); + + expect(jest.mocked(OptionItem)).toHaveBeenCalled(); + expect(jest.mocked(OptionItem).mock.calls[0][0]).toEqual(expect.objectContaining({ + label: 'Option label', + labelNumberOfLines: 1, + type: 'default', + testID: 'base-option', + })); + }); +}); diff --git a/app/components/common_post_options/base_option/index.tsx b/app/components/common_post_options/base_option/index.tsx index 58d12b124..94f4d7648 100644 --- a/app/components/common_post_options/base_option/index.tsx +++ b/app/components/common_post_options/base_option/index.tsx @@ -29,6 +29,7 @@ const BaseOption = ({ destructive={isDestructive} icon={iconName} label={intl.formatMessage(message)} + labelNumberOfLines={1} testID={testID} type='default' /> diff --git a/app/components/option_item/index.tsx b/app/components/option_item/index.tsx index 67864b529..6c0e73f59 100644 --- a/app/components/option_item/index.tsx +++ b/app/components/option_item/index.tsx @@ -132,6 +132,7 @@ export type OptionItemProps = { value?: string; onLayout?: (event: LayoutChangeEvent) => void; descriptionNumberOfLines?: number; + labelNumberOfLines?: number; longInfo?: boolean; nonDestructiveDescription?: boolean; isRadioCheckmark?: boolean; @@ -155,6 +156,7 @@ const OptionItem = ({ value, onLayout, descriptionNumberOfLines, + labelNumberOfLines = 2, longInfo, nonDestructiveDescription = false, isRadioCheckmark = false, @@ -326,7 +328,7 @@ const OptionItem = ({ {label} diff --git a/app/components/option_item/option_item.test.tsx b/app/components/option_item/option_item.test.tsx index 94cd6e35b..182805f0f 100644 --- a/app/components/option_item/option_item.test.tsx +++ b/app/components/option_item/option_item.test.tsx @@ -40,6 +40,7 @@ describe('OptionItem', () => { const label = getByText('Test Option'); expect(label).toBeTruthy(); expect(label).toHaveStyle({fontWeight: '400'}); + expect(label.props.numberOfLines).toBe(2); // No description expect(queryByTestId('option-item.description')).toBeNull(); @@ -65,6 +66,16 @@ describe('OptionItem', () => { expect(queryByTestId('option-item.arrow.icon')).toBeNull(); }); + it('respects custom label number of lines', () => { + const props = getBaseProps(); + props.labelNumberOfLines = 1; + + const {getByText} = renderWithIntlAndTheme(); + + const label = getByText('Test Option'); + expect(label.props.numberOfLines).toBe(1); + }); + it('renders with description when provided', () => { const props = getBaseProps(); props.description = 'Test description'; diff --git a/app/screens/post_options/options/app_bindings_post_option.tsx b/app/screens/post_options/options/app_bindings_post_option.tsx index c78bf5fb7..a65242811 100644 --- a/app/screens/post_options/options/app_bindings_post_option.tsx +++ b/app/screens/post_options/options/app_bindings_post_option.tsx @@ -77,6 +77,7 @@ const BindingOptionItem = ({binding, onPress}: {binding: AppBinding; onPress: (b return (