From b4216c3458bdc44996a645e41ec12e5f1183d8ec Mon Sep 17 00:00:00 2001 From: Ahmed Abdelsalam Date: Tue, 24 Oct 2023 09:38:43 +0200 Subject: [PATCH] Change: Change opening direction of dropdown menus Dropdown menus for select and multi-select components can now open upwards if space below is not enough to prevent extending beyond the viewport. --- .../__snapshots__/selectelement.js.snap | 70 +++++++++++++++++++ .../form/__tests__/selectelement.js | 33 ++++++++- src/web/components/form/multiselect.js | 13 +++- src/web/components/form/select.js | 13 +++- src/web/components/form/selectelements.js | 13 +++- 5 files changed, 136 insertions(+), 6 deletions(-) diff --git a/src/web/components/form/__tests__/__snapshots__/selectelement.js.snap b/src/web/components/form/__tests__/__snapshots__/selectelement.js.snap index 3432c81098..0a3b4ad880 100644 --- a/src/web/components/form/__tests__/__snapshots__/selectelement.js.snap +++ b/src/web/components/form/__tests__/__snapshots__/selectelement.js.snap @@ -216,6 +216,76 @@ exports[`Menu tests should render 1`] = ` /> `; +exports[`Menu tests should render with open direction downwards 1`] = ` +.c0 { + outline: 0; + border-radius: 0 0 4px 4px; + -webkit-transition: opacity 0.1s ease; + transition: opacity 0.1s ease; + box-shadow: 0 2px 3px 0 rgba(34, 36, 38, 0.15); + border: 1px solid #bfbfbf; + background-color: #fff; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + position: absolute; + z-index: 600; + margin-top: -1px; + box-sizing: border-box; + top: 120px; + left: 50px; + white-space: nowrap; +} + +
+`; + +exports[`Menu tests should render with open direction upwards 1`] = ` +.c0 { + outline: 0; + border-radius: 0 0 4px 4px; + -webkit-transition: opacity 0.1s ease; + transition: opacity 0.1s ease; + box-shadow: 0 2px 3px 0 rgba(34, 36, 38, 0.15); + border: 1px solid #bfbfbf; + background-color: #fff; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + position: absolute; + z-index: 600; + margin-top: -1px; + box-sizing: border-box; + top: 25px; + left: 50px; + white-space: nowrap; +} + +
+`; + exports[`Menu tests should render with position adjust 1`] = ` .c0 { outline: 0; diff --git a/src/web/components/form/__tests__/selectelement.js b/src/web/components/form/__tests__/selectelement.js index ae93751b5b..0b4471dc3e 100644 --- a/src/web/components/form/__tests__/selectelement.js +++ b/src/web/components/form/__tests__/selectelement.js @@ -209,6 +209,7 @@ class MenuTestComponent extends React.Component { this.target = React.createRef(); this.mockBoundingClientRect = this.props.mockBoundingClientRect; + this.notifyRefAssigned = jest.fn(); } render() { @@ -235,7 +236,13 @@ class MenuTestComponent extends React.Component { className={this.mockBoundingClientRect ? 'multiselect-scroll' : ''} style={{width: '200px', height: '100px'}} /> - {hasTarget && } + {hasTarget && ( + + )}
); } @@ -246,6 +253,7 @@ MenuTestComponent.propTypes = { }; describe('Menu tests', () => { + window.innerHeight = 180; const renderTest = props => { const {rerender, ...other} = render(); rerender(); @@ -282,12 +290,33 @@ describe('Menu tests', () => { }); test('should not render without target', () => { - const {queryByTestId} = render(); + const notifyRefAssigned = jest.fn(); + const {queryByTestId} = render( + , + ); const menu = queryByTestId('select-menu'); expect(menu).toBeNull(); }); + + test('should render with open direction upwards', () => { + const {getByTestId} = renderTest({ + mockBoundingClientRect: true, + menuHeight: 75, + }); + const menu = getByTestId('select-menu'); + expect(menu).toMatchSnapshot(); + }); + + test('should render with open direction downwards', () => { + const {getByTestId} = renderTest({ + mockBoundingClientRect: true, + menuHeight: 55, + }); + const menu = getByTestId('select-menu'); + expect(menu).toMatchSnapshot(); + }); }); // vim: set ts=2 sw=2 tw=80: diff --git a/src/web/components/form/multiselect.js b/src/web/components/form/multiselect.js index ff4c919d31..ed9c076212 100644 --- a/src/web/components/form/multiselect.js +++ b/src/web/components/form/multiselect.js @@ -85,15 +85,22 @@ class MultiSelect extends React.Component { this.state = { search: '', + isMenuRefAssigned: false, }; this.input = React.createRef(); this.box = React.createRef(); + this.menu = React.createRef(); this.handleRemoveItem = this.handleRemoveItem.bind(this); this.handleSearch = this.handleSearch.bind(this); this.handleSelect = this.handleSelect.bind(this); this.renderItem = this.renderItem.bind(this); + this.notifyRefAssigned = this.notifyRefAssigned.bind(this); + } + + notifyRefAssigned() { + this.setState({isMenuRefAssigned: true}); } notifyChange(value) { @@ -242,9 +249,13 @@ class MultiSelect extends React.Component { {isOpen && !disabled && ( {isOpen && !disabled && ( ); @@ -225,6 +232,8 @@ class MenuComponent extends React.Component { MenuComponent.propTypes = { forwardedRef: PropTypes.ref, + menuHeight: PropTypes.number, + notifyRefAssigned: PropTypes.func, target: PropTypes.ref, };