Trying to use react-custom-scrollbars inside a custom MenuList component makes the keyboard navigation of react-select break.
Example:
// CustomMenuList.tsx
import React from "react";
import { components } from "react-select";
import { Scrollbars } from "react-custom-scrollbars";
import styled from "styled-components";
export const MenuList = (props: any) => {
return (
<components.MenuList {...props}>
<div style={{ height: 200 }}>
<Scrollbars>
{props.children}
</Scrollbars>
</div>
</components.MenuList>
);
};
// App.tsx
<Select
components={{ MenuList }}
captureMenuScroll={false} // custom scrollbar doesn't scroll if this is true
/>
With the above code, the dropdown list no longer scrolls to the focused option when trying to navigate using the keyboard arrow keys. However, if we remove the <Scrollbars> component, then the keyboard navigation works as expected and the menu starts scrolling as we press the down arrow key repeatedly.
I am facing the same issue using version in package.json
"react-select": "^3.1.1",
"react-custom-scrollbars": "^4.2.1",
@cseas @kabdelkareem
The Select component requires a ref to the scrollable container of the options list to scroll to the focused option. The MenuList component receives for this the innerRef prop.
But we can麓t just simply set the ref prop on the Scrollbars component, because this would be a reference to the component, not the actual DOM element.
For this we would have to do as follows:
const MenuList = ({ children, innerRef, ...props }) => {
const intermediateRef = React.useRef();
React.useEffect(() => {
innerRef(intermediateRef.current ? intermediateRef.current.view : null);
}, [innerRef, intermediateRef]);
return (
<components.MenuList {...props}>
<div style={{ height: 200 }}>
<Scrollbars ref={intermediateRef}>{children}</Scrollbars>
</div>
</components.MenuList>
);
};
At first we need the reference to the Scrollbars component. It contains a reference to the needed DOM element. Then as soon as the reference exists we set the reference to the scrolling DOM element as our innerRef reference.
Greetings @cseas @kabdelkareem,
Can you confirm that the above solution works for you and if so close the ticket?
My team figured that a custom JavaScript scrollbar isn't the best idea and we'd like to use the native one. So we just added the following styles to menuList so at least the scrollbar is styled on webkit browsers:
"::-webkit-scrollbar": {
width: "0.6rem",
},
"::-webkit-scrollbar-track": {
background: "rgba(0, 0, 0, 0)", // transparent
borderRadius: "1rem",
},
"::-webkit-scrollbar-thumb": {
background: state.theme.colors.primary25,
borderRadius: "1rem",
boxShadow: "inset 0 0 0.6rem rgba(0, 0, 0, 0.2)",
},
"::-webkit-scrollbar-thumb:hover": {
background: Color.silver,
}
Full example here.
Maybe @kabdelkareem can confirm whether the above solution using ref works for their use case? I'll close the Issue for now.
@cseas I have tried it and it is working. thanks @Rall3n
Most helpful comment
@cseas @kabdelkareem
The
Selectcomponent requires arefto the scrollable container of the options list to scroll to the focused option. TheMenuListcomponent receives for this theinnerRefprop.But we can麓t just simply set the
refprop on theScrollbarscomponent, because this would be a reference to the component, not the actual DOM element.For this we would have to do as follows:
At first we need the reference to the
Scrollbarscomponent. It contains a reference to the needed DOM element. Then as soon as the reference exists we set the reference to the scrolling DOM element as ourinnerRefreference.