-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
recalculate menu top position on scroll when using menuPosition='fixed'
#3646
Comments
Bumped into while searching for menu. I came up with a hacky solution for an older version of Might be of use: updateMenuPosition = () => {
this.setState((prevState) => {
const wrapper = $(this.wrapperRef);
const menuElement = $('.Select-menu-outer');
const isMenuOpen = menuElement.length > 0;
let menuPositionStyling = null;
let maxMenuHeightOffset = null;
if (isMenuOpen) {
const menuBoundingBox = menuElement[0].getBoundingClientRect();
const realMenuHeight = menuBoundingBox.height;
const unconstrainedMenuHeight = realMenuHeight - prevState.maxMenuHeightOffset;
const scrollableContainer = wrapper.parents('.scrollable-container')[0];
const scrollableContainerBoundingBox = scrollableContainer != null ? scrollableContainer.getBoundingClientRect() : null;
const controlBoundingBox = wrapper.find('.Select-control')[0].getBoundingClientRect();
const borderOffset = 2;
menuPositionStyling = {
position: 'fixed',
top: controlBoundingBox.top + controlBoundingBox.height + borderOffset, // + 2 to go below border
left: controlBoundingBox.left,
};
// hack: safari scrolling element is <body>, other browsers is <html>. Getting/setting scrollTop on this element will make the below functionality work on both browsers while still using html element for boundaries.
// document.scrollingElement is not defined for IE 11, so fallback to htmlElement.
const htmlElement = document.documentElement;
const pageScrollingElement = document.scrollingElement || htmlElement;
const pageScrollable = htmlElement.clientHeight < htmlElement.scrollHeight;
let heightBoundary = window.innerHeight;
let hide = controlBoundingBox.top < 0 || controlBoundingBox.bottom > htmlElement.clientHeight;
if (pageScrollable) {
const remainingScrollDistance = htmlElement.scrollHeight - pageScrollingElement.scrollTop - htmlElement.clientHeight;
heightBoundary += remainingScrollDistance;
}
if (menuPositionStyling.top + unconstrainedMenuHeight > heightBoundary) { // place dropdown on top
if (scrollableContainerBoundingBox != null &&
(controlBoundingBox.top < scrollableContainerBoundingBox.top || controlBoundingBox.top > scrollableContainerBoundingBox.bottom)) {
hide = true;
}
menuPositionStyling.top = controlBoundingBox.top - borderOffset - unconstrainedMenuHeight;
if (menuPositionStyling.top < 0) {
maxMenuHeightOffset = menuPositionStyling.top;
menuPositionStyling.top = 0;
}
} else { // dropdown on bottom
if (scrollableContainerBoundingBox != null &&
(controlBoundingBox.bottom < scrollableContainerBoundingBox.top || controlBoundingBox.bottom > scrollableContainerBoundingBox.bottom)) {
hide = true;
}
if (!hide) {
const calculatedMenuBottom = menuPositionStyling.top + menuBoundingBox.height + pageScrollingElement.scrollTop;
if (pageScrollable && calculatedMenuBottom > htmlElement.clientHeight) {
pageScrollingElement.scrollTop = Math.max(calculatedMenuBottom - htmlElement.clientHeight, pageScrollingElement.scrollTop);
}
}
}
if (hide) {
menuPositionStyling.display = 'none';
}
}
return {
menuPositionStyling,
maxMenuHeightOffset,
};
}, () => this.forceUpdate());
} Had a window scroll handler call that. |
Is there any update on this issue? |
FWIW, I currently use this hack handleCloseMenuOnScroll = () => {
// forcing select menu re-rendering on scroll
this.setState({ top: 0 });
// as expected do not close the menu on scroll
return false;
}
<Select
...
styles={{
menuPortal: base => ({
// this just updates the menuPortal style to trigger a rerender
top: this.state.top,
...base,
}),
}}
closeMenuOnScroll={this.handleCloseMenuOnScroll}
/> |
hi, did anyone find a way to fix it? |
@HodayaGruz have you tried #3646 (comment) above ? |
@xmile1 i tried, the menu is stick to the top of the page |
Hello - Thanks for reporting this issue. This bug has been reported multiple times as per issue #4088. A new master issue #4088 has since been created to keep track this this bug. This new issue will exist as the source of truth going forward to investigate the issue, report findings, and implement a bug fix. We'll take into account all the details above while investigating. If you feel this issue has been wrongly closed as it isn't related to the new master issue #4088, please let us know and we'll take another look. Thank you! |
Hi, thanks for having this awesome library, it has been very helpful.
There seems to be a bug when using menuPosition fixed with react select except of course I am missing something.
The menu position should be with the select box when scrolling the page vertically but its fixed and isn't recalculated on scroll.
I have reproduced it here
https://codesandbox.io/s/react-codesandboxer-example-xy47y
The text was updated successfully, but these errors were encountered: