Skip to content

Commit

Permalink
Change: Change opening direction of dropdown menus
Browse files Browse the repository at this point in the history
Dropdown menus for select and multi-select components can now open upwards
if space below is not enough to prevent extending beyond the viewport.
  • Loading branch information
a-h-abdelsalam authored and timopollmeier committed Oct 26, 2023
1 parent bf25293 commit b4216c3
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
<div
class="c0"
data-testid="select-menu"
right="-10"
width="100"
x="50"
y="120"
/>
`;

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;
}
<div
class="c0"
data-testid="select-menu"
right="-10"
width="100"
x="50"
y="25"
/>
`;

exports[`Menu tests should render with position adjust 1`] = `
.c0 {
outline: 0;
Expand Down
33 changes: 31 additions & 2 deletions src/web/components/form/__tests__/selectelement.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ class MenuTestComponent extends React.Component {

this.target = React.createRef();
this.mockBoundingClientRect = this.props.mockBoundingClientRect;
this.notifyRefAssigned = jest.fn();
}

render() {
Expand All @@ -235,7 +236,13 @@ class MenuTestComponent extends React.Component {
className={this.mockBoundingClientRect ? 'multiselect-scroll' : ''}
style={{width: '200px', height: '100px'}}
/>
{hasTarget && <Menu {...this.props} target={this.target} />}
{hasTarget && (
<Menu
{...this.props}
notifyRefAssigned={this.notifyRefAssigned}
target={this.target}
/>
)}
</div>
);
}
Expand All @@ -246,6 +253,7 @@ MenuTestComponent.propTypes = {
};

describe('Menu tests', () => {
window.innerHeight = 180;
const renderTest = props => {
const {rerender, ...other} = render(<MenuTestComponent {...props} />);
rerender(<MenuTestComponent {...props} />);
Expand Down Expand Up @@ -282,12 +290,33 @@ describe('Menu tests', () => {
});

test('should not render without target', () => {
const {queryByTestId} = render(<Menu target={null} />);
const notifyRefAssigned = jest.fn();
const {queryByTestId} = render(
<Menu target={null} notifyRefAssigned={notifyRefAssigned} />,
);

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:
13 changes: 12 additions & 1 deletion src/web/components/form/multiselect.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -242,9 +249,13 @@ class MultiSelect extends React.Component {
</Box>
{isOpen && !disabled && (
<Menu
{...getMenuProps({})}
{...getMenuProps({ref: this.menu})}
position={menuPosition}
target={this.box}
menuHeight={
this.menu.current?.getBoundingClientRect().height
}
notifyRefAssigned={this.notifyRefAssigned}
>
<Input
{...getInputProps({
Expand Down
13 changes: 12 additions & 1 deletion src/web/components/form/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,21 @@ class Select extends React.Component {

this.state = {
search: '',
isMenuRefAssigned: false,
};

this.input = React.createRef();
this.box = React.createRef();
this.menu = React.createRef();

this.handleChange = this.handleChange.bind(this);
this.handleSearch = this.handleSearch.bind(this);
this.handleSelect = this.handleSelect.bind(this);
this.notifyRefAssigned = this.notifyRefAssigned.bind(this);
}

notifyRefAssigned() {
this.setState({isMenuRefAssigned: true});
}

handleChange(value) {
Expand Down Expand Up @@ -237,9 +244,13 @@ class Select extends React.Component {
</Box>
{isOpen && !disabled && (
<Menu
{...getMenuProps({})}
{...getMenuProps({ref: this.menu})}
position={menuPosition}
target={this.box}
menuHeight={
this.menu.current?.getBoundingClientRect().height
}
notifyRefAssigned={this.notifyRefAssigned}
>
<Input
{...getInputProps({
Expand Down
13 changes: 11 additions & 2 deletions src/web/components/form/selectelements.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ class MenuComponent extends React.Component {
if (this.eventTarget !== window) {
window.addEventListener('scroll', this.handleScroll, {passive: true});
}
this.props.notifyRefAssigned();
}

componentWillUnmount() {
Expand All @@ -195,7 +196,7 @@ class MenuComponent extends React.Component {
}

render() {
const {target, forwardedRef, ...props} = this.props;
const {target, forwardedRef, menuHeight, ...props} = this.props;

if (!hasValue(target) || target.current === null) {
return null;
Expand All @@ -207,6 +208,8 @@ class MenuComponent extends React.Component {

const {height, width, right, left, top} = rect;

const y = top + getScrollY() + height;

return (
<Portal>
<MenuContainer
Expand All @@ -216,7 +219,11 @@ class MenuComponent extends React.Component {
right={document.body.clientWidth - right}
width={width}
x={left + getScrollX()}
y={top + getScrollY() + height}
y={
hasValue(menuHeight) && window.innerHeight - y < menuHeight
? top + getScrollY() - menuHeight
: y
}
/>
</Portal>
);
Expand All @@ -225,6 +232,8 @@ class MenuComponent extends React.Component {

MenuComponent.propTypes = {
forwardedRef: PropTypes.ref,
menuHeight: PropTypes.number,
notifyRefAssigned: PropTypes.func,
target: PropTypes.ref,
};

Expand Down

0 comments on commit b4216c3

Please sign in to comment.