I am trying to add Simplebar scrollbar to the MUI Material Autocomplete component, instead of the default browser one. All works but doing that I've lost the ability to navigate the options list with the keyboard.
There is this snippet from the MUI docs
ListboxComponent If you provide a custom ListboxComponent prop, you need to make sure that the intended scroll container has the role attribute set to listbox. This ensures the correct behavior of the scroll, for example when using the keyboard to navigate.
But I have no idea how to do that.
The following code is from the MUI docs, first autocomplete example with custom ListboxComponenet and shortened movie list. (https://mui.com/components/autocomplete/)
import * as React from 'react';
import TextField from '@mui/material/TextField';
import Autocomplete from '@mui/material/Autocomplete';
import SimpleBar from "simplebar-react";
import "simplebar/dist/simplebar.min.css";
export default function ComboBox() {
return (
<Autocomplete
disablePortal
id="combo-box-demo"
options={top100Films}
ListboxComponent={SimpleBar}
sx={{ width: 300 }}
renderInput={(params) => <TextField {...params} label="Movie" />}
/>
);
}
// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const top100Films = [
{ label: 'City of God', year: 2002 },
{ label: 'Se7en', year: 1995 },
{ label: 'The Silence of the Lambs', year: 1991 },
{ label: "It's a Wonderful Life", year: 1946 },
{ label: 'Life Is Beautiful', year: 1997 },
{ label: 'The Usual Suspects', year: 1995 },
{ label: 'LΓ©on: The Professional', year: 1994 },
{ label: 'Spirited Away', year: 2001 },
{ label: 'Saving Private Ryan', year: 1998 },
{ label: 'Once Upon a Time in the West', year: 1968 },
{ label: 'American History X', year: 1998 },
{ label: 'Interstellar', year: 2014 },
{ label: 'Casablanca', year: 1942 },
{ label: 'City Lights', year: 1931 },
{ label: 'Psycho', year: 1960 },
{ label: 'The Green Mile', year: 1999 },
{ label: 'The Intouchables', year: 2011 },
{ label: 'Modern Times', year: 1936 },
{ label: 'Raiders of the Lost Ark', year: 1981 },
{ label: 'Rear Window', year: 1954 },
{ label: 'The Pianist', year: 2002 },
{ label: 'The Departed', year: 2006 },
{ label: 'Terminator 2: Judgment Day', year: 1991 },
{ label: 'Back to the Future', year: 1985 },
{ label: 'Whiplash', year: 2014 },
{ label: 'Gladiator', year: 2000 },
{ label: 'Memento', year: 2000 },
];
I have also tried the following but that also doesn't seem to work.
ListboxComponent={(props) => <SimpleBar {...props} role="listbox" />}
Any help would be appreciated, thanks.
The problem is actually very complicated. Looking at its implementation, <SimpleBar />
doesn't pass either the React ref
or the role
prop to the correct element. The correct element I believe is .scrollbar-content
, which is very deeply nested and basically untouchable.
ETA: In case you thought of getting cheesy with document.querySelectorAll
setAttribute
shenanigans, that will not work. The ref
also needs to point at the correct element, and I don't think that's codeable on the workspace side.
The cleanest solution I can think of is to use Yarn 3 (π) and patch simplebar-react
yourself, passing the needed props to .scrollbar-content
. Then you do:
const ListboxSimpleBar = React.forwardRef(function ListboxSimpleBar(props, ref) {
return <SimpleBar {...props} role='listbox' listboxRef={ref} />
}
// ...
ListboxComponent={ListboxSimpleBar}
The less clean solution is to fork the repo, patch it, and install it as a git dependency. Or publish to npm once you're sure it works and install as a regular dependency. That's the recommended method if you don't use Yarn 3 (π). It's much more tedious and won't receive updates, but it is an option that exists.
The least clean solution is to copypasterino the simplebar-react code in your own workspace, edit it and import it in lieu of the real simplebar-react. Hackier, messier and funnier option 2, but only just barely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With