From 26ff54990b8bd0f1ebbe94b9da5b5a0a896d5cc5 Mon Sep 17 00:00:00 2001 From: Cee Chen <549407+cee-chen@users.noreply.github.com> Date: Thu, 21 Sep 2023 11:10:55 -0700 Subject: [PATCH] [EuiComboBox] Fixes/reversions for Kibana FTR (#7212) --- .../__snapshots__/combo_box.test.tsx.snap | 198 ++---------------- src/components/combo_box/combo_box.spec.tsx | 10 +- src/components/combo_box/combo_box.test.tsx | 21 +- .../_combo_box_options_list.scss | 8 + .../combo_box_options_list.tsx | 25 ++- .../__snapshots__/text_truncate.test.tsx.snap | 3 +- .../text_truncate/text_truncate.styles.ts | 4 +- .../text_truncate/text_truncate.tsx | 20 +- upcoming_changelogs/7212.md | 5 + 9 files changed, 87 insertions(+), 207 deletions(-) create mode 100644 upcoming_changelogs/7212.md diff --git a/src/components/combo_box/__snapshots__/combo_box.test.tsx.snap b/src/components/combo_box/__snapshots__/combo_box.test.tsx.snap index d26f12d9876..1437ce0adf0 100644 --- a/src/components/combo_box/__snapshots__/combo_box.test.tsx.snap +++ b/src/components/combo_box/__snapshots__/combo_box.test.tsx.snap @@ -547,6 +547,7 @@ exports[`props option.prepend & option.append renders in the options dropdown 1` id="generated-id__option-0" role="option" style="position: absolute; left: 0px; top: 0px; height: 29px; width: 100%;" + title="1" type="button" > -
-
+ 1
@@ -597,6 +583,7 @@ exports[`props option.prepend & option.append renders in the options dropdown 1` id="generated-id__option-1" role="option" style="position: absolute; left: 0px; top: 29px; height: 29px; width: 100%;" + title="2" type="button" > -
-
+ 2
-
-
+ Titan
@@ -770,6 +728,7 @@ exports[`props options list is rendered 1`] = ` id="generated-id__option-1" role="option" style="position: absolute; left: 0px; top: 29px; height: 29px; width: 100%;" + title="Enceladus" type="button" > -
-
+ Enceladus
@@ -811,6 +755,7 @@ exports[`props options list is rendered 1`] = ` id="generated-id__option-2" role="option" style="position: absolute; left: 0px; top: 58px; height: 29px; width: 100%;" + title="Mimas" type="button" > -
-
+ Mimas
@@ -852,6 +782,7 @@ exports[`props options list is rendered 1`] = ` id="generated-id__option-3" role="option" style="position: absolute; left: 0px; top: 87px; height: 29px; width: 100%;" + title="Dione" type="button" > -
-
+ Dione
@@ -893,6 +809,7 @@ exports[`props options list is rendered 1`] = ` id="generated-id__option-4" role="option" style="position: absolute; left: 0px; top: 116px; height: 29px; width: 100%;" + title="Iapetus" type="button" > -
-
+ Iapetus
@@ -934,6 +836,7 @@ exports[`props options list is rendered 1`] = ` id="generated-id__option-5" role="option" style="position: absolute; left: 0px; top: 145px; height: 29px; width: 100%;" + title="Phoebe" type="button" > -
-
+ Phoebe
@@ -975,6 +863,7 @@ exports[`props options list is rendered 1`] = ` id="generated-id__option-6" role="option" style="position: absolute; left: 0px; top: 174px; height: 29px; width: 100%;" + title="Rhea" type="button" > -
-
+ Rhea
@@ -1016,6 +890,7 @@ exports[`props options list is rendered 1`] = ` id="generated-id__option-7" role="option" style="position: absolute; left: 0px; top: 203px; height: 29px; width: 100%;" + title="Pandora is one of Saturn's moons, named for a Titaness of Greek mythology" type="button" > -
-
+ Pandora is one of Saturn's moons, named for a Titaness of Greek mythology
@@ -1057,6 +917,7 @@ exports[`props options list is rendered 1`] = ` id="generated-id__option-8" role="option" style="position: absolute; left: 0px; top: 232px; height: 29px; width: 100%;" + title="Tethys" type="button" > -
-
+ Tethys
diff --git a/src/components/combo_box/combo_box.spec.tsx b/src/components/combo_box/combo_box.spec.tsx index 6fe737d7003..4910941a1f5 100644 --- a/src/components/combo_box/combo_box.spec.tsx +++ b/src/components/combo_box/combo_box.spec.tsx @@ -58,16 +58,13 @@ describe('EuiComboBox', () => { ], }; - it('defaults to end truncation', () => { + it('defaults to CSS truncation', () => { cy.realMount(); cy.get('[data-test-subj="comboBoxInput"]').realClick(); - cy.get('[data-test-subj="truncatedText"]').should( - 'have.text', - 'Lorem ipsum dolor sit a…' - ); + cy.get('.euiTextTruncate').should('not.exist'); }); - it('allows customizing truncationProps', () => { + it('renders EuiTextTruncate when truncationProps are passed', () => { cy.realMount( { /> ); cy.get('[data-test-subj="comboBoxInput"]').realClick(); + cy.get('.euiTextTruncate').should('exist'); cy.get('[data-test-subj="truncatedText"]').should( 'have.text', 'Lorem ipsum …piscing elit.' diff --git a/src/components/combo_box/combo_box.test.tsx b/src/components/combo_box/combo_box.test.tsx index e2151d9ed57..9b1559bfe00 100644 --- a/src/components/combo_box/combo_box.test.tsx +++ b/src/components/combo_box/combo_box.test.tsx @@ -67,14 +67,19 @@ const options: TitanOption[] = [ describe('EuiComboBox', () => { shouldRenderCustomStyles(); - shouldRenderCustomStyles(, { - skip: { parentTest: true }, - childProps: ['truncationProps', 'options[0]'], - renderCallback: async ({ getByTestSubject, findAllByTestSubject }) => { - fireEvent.click(getByTestSubject('comboBoxToggleListButton')); - await findAllByTestSubject('truncatedText'); - }, - }); + shouldRenderCustomStyles( + , + { + skip: { parentTest: true }, + childProps: ['truncationProps', 'options[0]'], + renderCallback: async ({ getByTestSubject, findAllByTestSubject }) => { + fireEvent.click(getByTestSubject('comboBoxToggleListButton')); + await findAllByTestSubject('truncatedText'); + }, + } + ); test('is rendered', () => { const { container } = render(); diff --git a/src/components/combo_box/combo_box_options_list/_combo_box_options_list.scss b/src/components/combo_box/combo_box_options_list/_combo_box_options_list.scss index cc094368710..46da053fed4 100644 --- a/src/components/combo_box/combo_box_options_list/_combo_box_options_list.scss +++ b/src/components/combo_box/combo_box_options_list/_combo_box_options_list.scss @@ -10,6 +10,14 @@ .euiFilterSelectItem__content { margin-block: 0 !important; // stylelint-disable-line declaration-no-important } + + /* Kibana FTR affordance - without this, Selenium complains about the overlaid + text intercepting the button click. Since `title` is always present, and + users can't highlight or copy combobox options anyway, we might as well + disable clicks on text */ + .euiTextTruncate { + pointer-events: none; + } } .euiComboBoxOptionsList__empty { diff --git a/src/components/combo_box/combo_box_options_list/combo_box_options_list.tsx b/src/components/combo_box/combo_box_options_list/combo_box_options_list.tsx index c554226e268..217e19e4d18 100644 --- a/src/components/combo_box/combo_box_options_list/combo_box_options_list.tsx +++ b/src/components/combo_box/combo_box_options_list/combo_box_options_list.tsx @@ -233,11 +233,12 @@ export class EuiComboBoxOptionsList extends Component< searchValue, rootId, } = this.props; - // Individual truncation settings should override component prop - const truncationProps = { - ...this.props.truncationProps, - ..._truncationProps, - }; + + const hasTruncationProps = this.props.truncationProps || _truncationProps; + const truncationProps = hasTruncationProps + ? // Individual truncation settings should override component prop + { ...this.props.truncationProps, ..._truncationProps } + : undefined; if (isGroupLabelOption) { return ( @@ -275,6 +276,7 @@ export class EuiComboBoxOptionsList extends Component< checked={checked} showIcons={singleSelection ? true : false} id={rootId(`_option-${index}`)} + title={label} {...rest} > @@ -306,12 +308,18 @@ export class EuiComboBoxOptionsList extends Component< renderTruncatedOption = ( text: string, - truncationProps: EuiComboBoxOptionsListProps['truncationProps'] + truncationProps?: EuiComboBoxOptionsListProps['truncationProps'] ) => { - if (!this.props.searchValue) { + const searchValue = this.props.searchValue.trim(); + + if (!truncationProps && !searchValue) { + // Default to CSS text-overflow + return text; + } + + if (!searchValue) { return ( extends Component< ); } - const searchValue = this.props.searchValue.trim(); const searchPositionStart = this.props.isCaseSensitive ? text.indexOf(searchValue) : text.toLowerCase().indexOf(searchValue.toLowerCase()); diff --git a/src/components/text_truncate/__snapshots__/text_truncate.test.tsx.snap b/src/components/text_truncate/__snapshots__/text_truncate.test.tsx.snap index ec4f25f2d0c..4a9cb530e59 100644 --- a/src/components/text_truncate/__snapshots__/text_truncate.test.tsx.snap +++ b/src/components/text_truncate/__snapshots__/text_truncate.test.tsx.snap @@ -3,10 +3,11 @@ exports[`EuiTextTruncate renders 1`] = `
Hello world diff --git a/src/components/text_truncate/text_truncate.styles.ts b/src/components/text_truncate/text_truncate.styles.ts index c79482aa0f2..9f7ea790b4f 100644 --- a/src/components/text_truncate/text_truncate.styles.ts +++ b/src/components/text_truncate/text_truncate.styles.ts @@ -25,13 +25,13 @@ export const euiTextTruncateStyles = { * and there'll be no need for the entire component at that point 🙏 */ // Makes the truncated text unselectable/un-clickable - truncatedText: css` + euiTextTruncate__truncatedText: css` user-select: none; pointer-events: none; `, // Positions the full text on top of the truncated text (so that clicking targets it) // and gives it a color opacity of 0 so that it's not actually visible - fullText: css` + euiTextTruncate__fullText: css` position: absolute; inset: 0; overflow: hidden; diff --git a/src/components/text_truncate/text_truncate.tsx b/src/components/text_truncate/text_truncate.tsx index f0a0df6e685..bcae09e1119 100644 --- a/src/components/text_truncate/text_truncate.tsx +++ b/src/components/text_truncate/text_truncate.tsx @@ -15,6 +15,7 @@ import React, { useMemo, useCallback, } from 'react'; +import classNames from 'classnames'; import { useCombinedRefs } from '../../services'; import { @@ -24,7 +25,7 @@ import { import type { CommonProps } from '../common'; import { TruncationUtilsWithDOM, TruncationUtilsWithCanvas } from './utils'; -import { euiTextTruncateStyles } from './text_truncate.styles'; +import { euiTextTruncateStyles as styles } from './text_truncate.styles'; const TRUNCATION_TYPES = ['end', 'start', 'startEnd', 'middle'] as const; export type EuiTextTruncationTypes = (typeof TRUNCATION_TYPES)[number]; @@ -129,6 +130,7 @@ const EuiTextTruncateWithWidth: FunctionComponent< ellipsis = '…', containerRef, measurementRenderAPI = 'dom', + className, ...rest }) => { // Note: This needs to be a state and not a ref to trigger a rerender on mount @@ -214,7 +216,8 @@ const EuiTextTruncateWithWidth: FunctionComponent< return (
{children ? children(truncatedText) : truncatedText} - + {text} ) : ( - {text} + + {children ? children(text) : text} + )}
); diff --git a/upcoming_changelogs/7212.md b/upcoming_changelogs/7212.md new file mode 100644 index 00000000000..ff31a846856 --- /dev/null +++ b/upcoming_changelogs/7212.md @@ -0,0 +1,5 @@ +**Bug fixes** + +- Fixed missing `className`s on `EuiTextTruncate` +- Fixed `title`s on `EuiComboBox` dropdown options to always be present +- Fixed `EuiComboBox` truncation issues when search is an empty space