让键盘导航与 MUI Autocomplete 和 SimpleBar 一起使用以进行反应

Sea*_*ead 7 typescript reactjs material-ui simplebar

我正在尝试将 Simplebar 滚动条添加到 MUI Material Autocomplete 组件,而不是默认的浏览器滚动条。所有这些都有效,但这样做我失去了使用键盘导航选项列表的能力。

\n

MUI 文档中有这个片段

\n
\n

ListboxComponent\n如果提供自定义 ListboxComponent 属性,则需要确保目标滚动容器的 role 属性设置为 listbox。这可以确保滚动的正确行为,例如在使用键盘导航时。

\n
\n

但我不知道该怎么做。

\n

以下代码来自 MUI 文档,第一个带有自定义 ListboxComponenet 和缩短的电影列表的自动完成示例。(https://mui.com/components/autocomplete/

\n
import * as React from \'react\';\nimport TextField from \'@mui/material/TextField\';\nimport Autocomplete from \'@mui/material/Autocomplete\';\n\nimport SimpleBar from "simplebar-react";\nimport "simplebar/dist/simplebar.min.css";\n\nexport default function ComboBox() {\n  return (\n    <Autocomplete\n      disablePortal\n      id="combo-box-demo"\n      options={top100Films}\n      ListboxComponent={SimpleBar}\n      sx={{ width: 300 }}\n      renderInput={(params) => <TextField {...params} label="Movie" />}\n    />\n  );\n}\n\n// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top\nconst top100Films = [\n  { label: \'City of God\', year: 2002 },\n  { label: \'Se7en\', year: 1995 },\n  { label: \'The Silence of the Lambs\', year: 1991 },\n  { label: "It\'s a Wonderful Life", year: 1946 },\n  { label: \'Life Is Beautiful\', year: 1997 },\n  { label: \'The Usual Suspects\', year: 1995 },\n  { label: \'L\xc3\xa9on: The Professional\', year: 1994 },\n  { label: \'Spirited Away\', year: 2001 },\n  { label: \'Saving Private Ryan\', year: 1998 },\n  { label: \'Once Upon a Time in the West\', year: 1968 },\n  { label: \'American History X\', year: 1998 },\n  { label: \'Interstellar\', year: 2014 },\n  { label: \'Casablanca\', year: 1942 },\n  { label: \'City Lights\', year: 1931 },\n  { label: \'Psycho\', year: 1960 },\n  { label: \'The Green Mile\', year: 1999 },\n  { label: \'The Intouchables\', year: 2011 },\n  { label: \'Modern Times\', year: 1936 },\n  { label: \'Raiders of the Lost Ark\', year: 1981 },\n  { label: \'Rear Window\', year: 1954 },\n  { label: \'The Pianist\', year: 2002 },\n  { label: \'The Departed\', year: 2006 },\n  { label: \'Terminator 2: Judgment Day\', year: 1991 },\n  { label: \'Back to the Future\', year: 1985 },\n  { label: \'Whiplash\', year: 2014 },\n  { label: \'Gladiator\', year: 2000 },\n  { label: \'Memento\', year: 2000 },\n];\n
Run Code Online (Sandbox Code Playgroud)\n

我也尝试过以下方法,但这似乎也不起作用。

\n
ListboxComponent={(props) => <SimpleBar {...props} role="listbox" />}\n
Run Code Online (Sandbox Code Playgroud)\n

任何帮助将不胜感激,谢谢。

\n

Sum*_*mer 1

问题其实很复杂。查看它的实现,<SimpleBar />没有将 Reactrefroleprop 传递给正确的元素。我认为正确的元素是.scrollbar-content,它嵌套得很深并且基本上无法触及。

ETA:如果你想搞些恶作剧document.querySelectorAll setAttribute,那是行不通的。还ref需要指向正确的元素,我认为这在工作区端是不可编码的。

我能想到的最干净的解决方案是使用 Yarn 3 () 并自行修补 simplebar-react,将所需的 props 传递给.scrollbar-content. 然后你就可以:

const ListboxSimpleBar = React.forwardRef(function ListboxSimpleBar(props, ref) {
  return <SimpleBar {...props} role='listbox' listboxRef={ref} />
}

// ...
ListboxComponent={ListboxSimpleBar}
Run Code Online (Sandbox Code Playgroud)

不太干净的解决方案是分叉repo,修补它,并将其安装为 git 依赖项。或者在确定它可以工作并作为常规依赖项安装后发布到 npm。如果您不使用 Yarn 3 (),这是推荐的方法。它更加乏味并且不会收到更新,但它是存在的一个选项。

最不干净的解决方案是将 simplebar-react 代码复制到您自己的工作区中,编辑并导入它来代替真正的 simplebar-react。选项 2 更黑客、更混乱、更有趣,但也只是勉强。