使用 react-beautiful-dnd 拖动时自动滚动水平 Mui TabList
Auto Scroll Horizontal Mui TabList on Drag with react-beautiful-dnd
我尝试使用 react-beautiful-dnd. The dnd is working fine but, I am facing an issue making horizontal list of tabs auto scroll while dragging when there are too many tabs to fit in the screen and the variant
prop of Mui TabList
is scrollable
. See this codesandbox example - https://codesandbox.io/s/draggable-and-scrollable-mui-tabs-xqgl77 在 Mui TabList 中实现拖放功能。这似乎是一个标准用例,因此必须有一些解决方案。请参考下面我的代码-
App.js
import * as React from "react";
import "./styles.css";
import DraggableTabsList from "./components/DraggableTabsList";
export default function App() {
const [tabs, setTabs] = React.useState(
[...Array(55)].map((_, index) => ({
id: `tab${index + 1}`,
label: `Tab ${index + 1}`,
value: `${index + 1}`,
content: `Content ${index + 1}`
}))
);
const onDragEnd = (result) => {
const newTabs = Array.from(tabs);
const draggedTab = newTabs.splice(result.source.index, 1)[0];
newTabs.splice(result.destination.index, 0, draggedTab);
setTabs(newTabs);
};
return (
<div className="App">
<DraggableTabsList onDragEnd={onDragEnd} tabs={tabs} />
</div>
);
}
/components/DraggableTabsList.jsx
import * as React from "react";
import Box from "@mui/material/Box";
import TabContext from "@mui/lab/TabContext";
import TabList from "@mui/lab/TabList";
import TabPanel from "@mui/lab/TabPanel";
import { DragDropContext, Droppable } from "react-beautiful-dnd";
import DraggableTab from "./DraggableTab";
import Tab from "@mui/material/Tab";
import Stack from "@mui/material/Stack";
export default function DraggableTabsList(props) {
const [value, setValue] = React.useState("1");
const handleChange = (event, newValue) => {
setValue(newValue);
};
const _renderTabList = (droppableProvided) => (
<TabList
onChange={handleChange}
aria-label="Draggable Tabs"
variant="scrollable"
>
{props.tabs.map((tab, index) => {
const child = <Tab label={tab.label} value={tab.value} key={index} />;
return (
<DraggableTab
label={tab.label}
value={tab.value}
index={index}
key={index}
child={child}
/>
);
})}
{droppableProvided ? droppableProvided.placeholder : null}
</TabList>
);
const _renderTabListWrappedInDroppable = () => (
<DragDropContext onDragEnd={props.onDragEnd}>
<Droppable droppableId="1" direction="horizontal">
{(droppableProvided) => (
<div
ref={droppableProvided.innerRef}
{...droppableProvided.droppableProps}
>
{_renderTabList(droppableProvided)}
</div>
)}
</Droppable>
</DragDropContext>
);
return (
<Box sx={{ width: "100%", typography: "body1" }}>
<TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Stack direction="column">{_renderTabListWrappedInDroppable()}</Stack>
</Box>
{props.tabs.map((tab, index) => (
<TabPanel value={tab.value} key={index}>
{tab.content}
</TabPanel>
))}
</TabContext>
</Box>
);
}
components/DraggableTab.jsx
import * as React from "react";
import { Draggable } from "react-beautiful-dnd";
export default function DraggableTab(props) {
return (
<Draggable
draggableId={`${props.index}`}
index={props.index}
disableInteractiveElementBlocking
>
{(draggableProvided) => (
<div
ref={draggableProvided.innerRef}
{...draggableProvided.draggableProps}
>
{React.cloneElement(props.child, {
...props,
...draggableProvided.dragHandleProps,
style: { cursor: "inherit" }
})}
</div>
)}
</Draggable>
);
}
谢谢!
这可以通过以下方式解决 - 在 /components/DraggableTabsList.jsx
中将 Droppable
包装在 div 容器中,样式为 {display:"flex", overflow:"auto"}
。新代码看起来像 -
<div style={{ display: 'flex', overflow: 'auto' }}>
<Droppable droppableId="1" direction="horizontal">
{(droppableProvided) => (
<div
ref={droppableProvided.innerRef}
{...droppableProvided.droppableProps}
>
{_renderTabList(droppableProvided)}
</div>
)}
</Droppable>
</div>
这将使选项卡可在整个选项卡列表中水平拖动,但不会呈现 MUI TabList 中的滚动按钮。
Codesandbox - https://codesandbox.io/s/mr9y10
我尝试使用 react-beautiful-dnd. The dnd is working fine but, I am facing an issue making horizontal list of tabs auto scroll while dragging when there are too many tabs to fit in the screen and the variant
prop of Mui TabList
is scrollable
. See this codesandbox example - https://codesandbox.io/s/draggable-and-scrollable-mui-tabs-xqgl77 在 Mui TabList 中实现拖放功能。这似乎是一个标准用例,因此必须有一些解决方案。请参考下面我的代码-
App.js
import * as React from "react";
import "./styles.css";
import DraggableTabsList from "./components/DraggableTabsList";
export default function App() {
const [tabs, setTabs] = React.useState(
[...Array(55)].map((_, index) => ({
id: `tab${index + 1}`,
label: `Tab ${index + 1}`,
value: `${index + 1}`,
content: `Content ${index + 1}`
}))
);
const onDragEnd = (result) => {
const newTabs = Array.from(tabs);
const draggedTab = newTabs.splice(result.source.index, 1)[0];
newTabs.splice(result.destination.index, 0, draggedTab);
setTabs(newTabs);
};
return (
<div className="App">
<DraggableTabsList onDragEnd={onDragEnd} tabs={tabs} />
</div>
);
}
/components/DraggableTabsList.jsx
import * as React from "react";
import Box from "@mui/material/Box";
import TabContext from "@mui/lab/TabContext";
import TabList from "@mui/lab/TabList";
import TabPanel from "@mui/lab/TabPanel";
import { DragDropContext, Droppable } from "react-beautiful-dnd";
import DraggableTab from "./DraggableTab";
import Tab from "@mui/material/Tab";
import Stack from "@mui/material/Stack";
export default function DraggableTabsList(props) {
const [value, setValue] = React.useState("1");
const handleChange = (event, newValue) => {
setValue(newValue);
};
const _renderTabList = (droppableProvided) => (
<TabList
onChange={handleChange}
aria-label="Draggable Tabs"
variant="scrollable"
>
{props.tabs.map((tab, index) => {
const child = <Tab label={tab.label} value={tab.value} key={index} />;
return (
<DraggableTab
label={tab.label}
value={tab.value}
index={index}
key={index}
child={child}
/>
);
})}
{droppableProvided ? droppableProvided.placeholder : null}
</TabList>
);
const _renderTabListWrappedInDroppable = () => (
<DragDropContext onDragEnd={props.onDragEnd}>
<Droppable droppableId="1" direction="horizontal">
{(droppableProvided) => (
<div
ref={droppableProvided.innerRef}
{...droppableProvided.droppableProps}
>
{_renderTabList(droppableProvided)}
</div>
)}
</Droppable>
</DragDropContext>
);
return (
<Box sx={{ width: "100%", typography: "body1" }}>
<TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Stack direction="column">{_renderTabListWrappedInDroppable()}</Stack>
</Box>
{props.tabs.map((tab, index) => (
<TabPanel value={tab.value} key={index}>
{tab.content}
</TabPanel>
))}
</TabContext>
</Box>
);
}
components/DraggableTab.jsx
import * as React from "react";
import { Draggable } from "react-beautiful-dnd";
export default function DraggableTab(props) {
return (
<Draggable
draggableId={`${props.index}`}
index={props.index}
disableInteractiveElementBlocking
>
{(draggableProvided) => (
<div
ref={draggableProvided.innerRef}
{...draggableProvided.draggableProps}
>
{React.cloneElement(props.child, {
...props,
...draggableProvided.dragHandleProps,
style: { cursor: "inherit" }
})}
</div>
)}
</Draggable>
);
}
谢谢!
这可以通过以下方式解决 - 在 /components/DraggableTabsList.jsx
中将 Droppable
包装在 div 容器中,样式为 {display:"flex", overflow:"auto"}
。新代码看起来像 -
<div style={{ display: 'flex', overflow: 'auto' }}>
<Droppable droppableId="1" direction="horizontal">
{(droppableProvided) => (
<div
ref={droppableProvided.innerRef}
{...droppableProvided.droppableProps}
>
{_renderTabList(droppableProvided)}
</div>
)}
</Droppable>
</div>
这将使选项卡可在整个选项卡列表中水平拖动,但不会呈现 MUI TabList 中的滚动按钮。
Codesandbox - https://codesandbox.io/s/mr9y10