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

[EuiComboBox] Replace autosizing input dependency with more performant utility #7215

Merged
merged 6 commits into from
Sep 26, 2023
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
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
"@hello-pangea/dnd": "^16.3.0",
"@types/lodash": "^4.14.198",
"@types/numeral": "^2.0.2",
"@types/react-input-autosize": "^2.2.1",
"@types/react-window": "^1.8.5",
"@types/refractor": "^3.0.2",
"@types/resize-observer-browser": "^0.1.7",
Expand All @@ -80,7 +79,6 @@
"react-dropzone": "^11.7.1",
"react-element-to-jsx-string": "^14.3.4",
"react-focus-on": "^3.9.1",
"react-input-autosize": "^3.0.0",
"react-is": "^17.0.2",
"react-remove-scroll-bar": "^2.3.4",
"react-virtualized-auto-sizer": "^1.0.20",
Expand Down
6 changes: 6 additions & 0 deletions scripts/jest/setup/mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ jest.mock('./../../../src/components/icon', () => {
return { EuiIcon };
});

jest.mock('./../../../src/components/text_truncate', () => {
const rest = jest.requireActual('./../../../src/components/text_truncate');
const utils = require('./../../../src/components/text_truncate/utils.testenv');
return { ...rest, ...utils };
});

jest.mock('./../../../src/services/accessibility', () => {
const a11y = jest.requireActual('./../../../src/services/accessibility');
const {
Expand Down
73 changes: 23 additions & 50 deletions src/components/combo_box/__snapshots__/combo_box.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,19 @@ exports[`EuiComboBox is rendered 1`] = `
data-test-subj="comboBoxInput"
tabindex="-1"
>
<div
<input
aria-autocomplete="list"
aria-controls=""
aria-expanded="false"
aria-invalid="false"
aria-label="aria-label"
class="euiComboBox__input"
style="font-size: 14px; display: inline-block;"
>
<input
aria-autocomplete="list"
aria-controls=""
aria-expanded="false"
aria-invalid="false"
aria-label="aria-label"
data-test-subj="comboBoxSearchInput"
id="generated-id__eui-combobox-id"
role="combobox"
style="box-sizing: content-box; width: 2px;"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-size: 14px; font-family: 'Inter',BlinkMacSystemFont,Helvetica,Arial,sans-serif; font-weight: 400; letter-spacing: normal; text-transform: none;"
/>
</div>
data-test-subj="comboBoxSearchInput"
id="generated-id__eui-combobox-id"
role="combobox"
style="inline-size: 2px;"
value=""
/>
</div>
<div
class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right euiFormControlLayoutIcons--absolute"
Expand Down Expand Up @@ -67,7 +60,6 @@ exports[`props aria-label attribute is rendered 1`] = `
>
<EuiComboBoxInput
aria-label="Test label"
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={false}
Expand Down Expand Up @@ -102,7 +94,6 @@ exports[`props aria-labelledby attribute is rendered 1`] = `
>
<EuiComboBoxInput
aria-labelledby="test-heading-id"
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={false}
Expand Down Expand Up @@ -136,7 +127,6 @@ exports[`props autoFocus is rendered 1`] = `
onKeyDown={[Function]}
>
<EuiComboBoxInput
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={true}
Expand Down Expand Up @@ -179,7 +169,6 @@ exports[`props custom ID is rendered 1`] = `
onKeyDown={[Function]}
>
<EuiComboBoxInput
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={true}
Expand Down Expand Up @@ -222,7 +211,6 @@ exports[`props delimiter is rendered 1`] = `
onKeyDown={[Function]}
>
<EuiComboBoxInput
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={true}
Expand Down Expand Up @@ -265,7 +253,6 @@ exports[`props full width is rendered 1`] = `
onKeyDown={[Function]}
>
<EuiComboBoxInput
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={true}
hasSelectedOptions={true}
Expand Down Expand Up @@ -305,7 +292,6 @@ exports[`props isClearable=false disallows user from clearing input when no opti
onKeyDown={[Function]}
>
<EuiComboBoxInput
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={false}
Expand Down Expand Up @@ -338,7 +324,6 @@ exports[`props isClearable=false disallows user from clearing input when options
onKeyDown={[Function]}
>
<EuiComboBoxInput
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={true}
Expand Down Expand Up @@ -380,7 +365,6 @@ exports[`props isDisabled is rendered 1`] = `
onKeyDown={[Function]}
>
<EuiComboBoxInput
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={true}
Expand Down Expand Up @@ -635,25 +619,18 @@ exports[`props options list is rendered 1`] = `
data-test-subj="comboBoxInput"
tabindex="-1"
>
<div
<input
aria-autocomplete="list"
aria-controls="generated-id_listbox"
aria-expanded="true"
aria-invalid="false"
class="euiComboBox__input"
style="font-size: 14px; display: inline-block;"
>
<input
aria-autocomplete="list"
aria-controls="generated-id_listbox"
aria-expanded="true"
aria-invalid="false"
data-test-subj="comboBoxSearchInput"
id="generated-id__eui-combobox-id"
role="combobox"
style="box-sizing: content-box; width: 2px;"
value=""
/>
<div
style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre; font-family: -webkit-small-control; letter-spacing: normal; text-transform: none;"
/>
</div>
data-test-subj="comboBoxSearchInput"
id="generated-id__eui-combobox-id"
role="combobox"
style="inline-size: 2px;"
value=""
/>
</div>
<div
class="euiFormControlLayoutIcons euiFormControlLayoutIcons--right euiFormControlLayoutIcons--absolute"
Expand Down Expand Up @@ -952,7 +929,6 @@ exports[`props selectedOptions are rendered 1`] = `
onKeyDown={[Function]}
>
<EuiComboBoxInput
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={true}
Expand Down Expand Up @@ -995,7 +971,6 @@ exports[`props singleSelection is rendered 1`] = `
onKeyDown={[Function]}
>
<EuiComboBoxInput
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={true}
Expand Down Expand Up @@ -1036,7 +1011,6 @@ exports[`props singleSelection prepend and append is rendered 1`] = `
>
<EuiComboBoxInput
append="String"
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={false}
Expand Down Expand Up @@ -1079,7 +1053,6 @@ exports[`props singleSelection selects existing option when opened 1`] = `
onKeyDown={[Function]}
>
<EuiComboBoxInput
autoSizeInputRef={[Function]}
compressed={false}
fullWidth={false}
hasSelectedOptions={true}
Expand Down
31 changes: 12 additions & 19 deletions src/components/combo_box/_combo_box.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,27 +55,20 @@
/**
* 1. Force field height to match other field heights.
* 2. Force input height to expand to fill this element.
* 3. Reset appearance on Safari.
* 4. Fix react-input-autosize appearance.
* 5. Prevent a lot of input from causing the react-input-autosize to overflow the container.
* 3. Reset input appearance to mimic text
*/
.euiComboBox__input {
// stylelint-disable-next-line declaration-no-important
display: inline-flex !important; /* 1 */
height: $euiSizeXL; /* 2 */
overflow: hidden; /* 5 */

> input {
@include euiFont;
appearance: none; /* 3 */
padding: 0;
border: none;
background: transparent;
font-size: $euiFontSizeS;
color: $euiTextColor;
margin: $euiSizeXS;
line-height: $euiLineHeight; /* 4 */
}
block-size: $euiSizeL; /* 2 */
min-inline-size: 2px;
max-inline-size: 100%;
margin: $euiSizeXS;

/* 3 */
appearance: none;
outline: none;
border: none;
background: transparent;
color: $euiTextColor;
}

&.euiComboBox-isOpen {
Expand Down
36 changes: 36 additions & 0 deletions src/components/combo_box/combo_box.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,42 @@ describe('EuiComboBox', () => {
});
});

describe('input auto sizing', () => {
it('resizes the width of the input based to fit the search text', () => {
cy.realMount(<EuiComboBox options={[]} />);
cy.get('[data-test-subj="comboBoxSearchInput"]').should(
'have.attr',
'style',
'inline-size: 2px;'
);

cy.get('[data-test-subj="comboBoxSearchInput"]').realClick();
cy.realType('lorem ipsum dolor');
cy.get('[data-test-subj="comboBoxSearchInput"]').should(
'have.attr',
'style',
'inline-size: 121px;'
);
});

it('does not exceed the maximum possible width of the input wrapper', () => {
cy.realMount(<EuiComboBox options={[]} />);
cy.get('[data-test-subj="comboBoxSearchInput"]').realClick();
cy.realType(
'Lorem ipsum dolor sit amet, consectetur adipiscing elit......'
);

cy.get('[data-test-subj="comboBoxSearchInput"]').should(
'have.attr',
'style',
'inline-size: 387px;'
);
cy.get('[data-test-subj="comboBoxSearchInput"]')
.invoke('width')
.should('be.eq', 354);
});
});

describe('truncation', () => {
const sharedProps = {
style: { width: 200 },
Expand Down
15 changes: 0 additions & 15 deletions src/components/combo_box/combo_box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import React, {
RefCallback,
} from 'react';
import classNames from 'classnames';
import AutosizeInput from 'react-input-autosize';

import { findPopoverPosition, htmlIdGenerator, keys } from '../../services';
import { getElementZIndex } from '../../services/popover';
Expand Down Expand Up @@ -256,12 +255,6 @@ export class EuiComboBox<T> extends Component<
});
}
};
autoSizeInputRefInstance: RefInstance<AutosizeInput & HTMLDivElement> = null;
autoSizeInputRefCallback: RefCallback<AutosizeInput & HTMLDivElement> = (
ref
) => {
this.autoSizeInputRefInstance = ref;
};

searchInputRefInstance: RefInstance<HTMLInputElement> = null;
searchInputRefCallback: RefCallback<HTMLInputElement> = (ref) => {
Expand Down Expand Up @@ -787,13 +780,6 @@ export class EuiComboBox<T> extends Component<

componentDidMount() {
this._isMounted = true;

// TODO: This will need to be called once the actual stylesheet loads.
setTimeout(() => {
if (this.autoSizeInputRefInstance) {
this.autoSizeInputRefInstance.copyInputStyles();
}
}, 100);
}

static getDerivedStateFromProps<T>(
Expand Down Expand Up @@ -1044,7 +1030,6 @@ export class EuiComboBox<T> extends Component<
ref={this.comboBoxRefCallback}
>
<EuiComboBoxInput
autoSizeInputRef={this.autoSizeInputRefCallback}
compressed={compressed}
focusedOptionId={
this.hasActiveOption()
Expand Down
Loading
Loading