I have this javascript draggable tabs component, it is a copy from another question here: mui-tablist with react beautiful dnd not auto scrolling on drag and it has a codesandbox
My aim is to migrate to typescript and eventually create something similar to the following mockup.
Migrating to typescript: I have taken the above question/answer and merged them together as best I can
import React from 'react';
import TabContext from "@mui/lab/TabContext";
import TabPanel from "@mui/lab/TabPanel";
import { DragDropContext, Droppable, DropResult } from "react-beautiful-dnd";
import { Draggable } from "react-beautiful-dnd";
import { Stack, styled, Tab, Tabs } from "@mui/material";
interface DraggableTabProps {
label: string;
value: string;
index: number;
key: number;
child: JSX.Element;
};
const DraggableTab = ( props: DraggableTabProps ) => {
return (
<Draggable
draggableId={`${props.index}`}
index={props.index}
disableInteractiveElementBlocking
>
{(draggableProvided) => (
<div
ref={draggableProvided.innerRef}
{...draggableProvided.draggableProps}
>
{React.cloneElement(props.child, {
...props,
...draggableProvided.dragHandleProps
})}
</div>
)}
</Draggable>
);
}
const StyledTabs = styled(Tabs)();
const StyledTab = styled(Tab)();
export default function DraggableTabComponent() {
const [value, setValue] = React.useState('1');
const handleChange = (event: React.SyntheticEvent, newValue: string) => {
setValue(newValue);
};
const [tabs, setTabs] = React.useState(
[...Array(25)].map((_, index) => ({
id: `tab${index + 1}`,
label: `Tab ${index + 1}`,
value: `${index + 1}`,
content: `Content ${index + 1}`
}))
);
const onDragEnd = (result: DropResult) => {
const newTabs = Array.from(tabs);
const draggedTab = newTabs.splice(result.source.index, 1)[0];
newTabs.splice(result.destination!.index, 0, draggedTab);
setTabs(newTabs);
};
return (
<TabContext value={value}>
<Stack>
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="1" direction="horizontal">
{(droppableProvided) => (
<StyledTabs
ref={droppableProvided.innerRef}
{...droppableProvided.droppableProps}
value={value}
onChange={handleChange}
variant="scrollable"
scrollButtons
allowScrollButtonsMobile
>
{tabs.map((tab, index) => {
const child = (
<StyledTab 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}
</StyledTabs>
)}
</Droppable>
</DragDropContext>
</Stack>
{tabs.map((tab, index) => (
<TabPanel value={tab.value} key={index}>
{tab.content}
</TabPanel>
))}
</TabContext>
);
}
This displays the tabs and I am able to click each tab and view its content, but I get an error along with each click for the draggable, e.g. on the first tab:
react_devtools_backend.js:4026 react-beautiful-dnd Unable to find draggable with id: 0
Could use some help to fix this up, thanks