I'm using the react-d3-tree library to create an organizational chart (org chart) in my React application. The org chart works great for smaller datasets, but as the organization grows larger, I'm faced with the challenge of enabling scrolling to view the entire org chart.
I've already integrated the library, and my org chart is rendering correctly. However, when the chart becomes too large to fit within the viewport, it gets cut off, and I can drag the whole org chart and view it but it's inconvenience.
I'd like to add a scrollbar to the org chart or the containing element so that users can scroll vertically or horizontally to explore the entire org chart, especially when it becomes larger.
This is the orgchart.tsx file,
import React, { useRef, useState } from "react";
import { Tree, RawNodeDatum } from "react-d3-tree";
import OrgData from "./orgData";
import {
TreeData,
updateStateMessage,
} from "../../../slices/treeSlice/treeData";
import { useSelector } from "react-redux";
import {Box, Button} from "@mui/material";
import { useAppSelector } from "../../../slices/store";
const OrgChart = ({}) => {
const nodeSize = { x: 400, y: 120 };
const foreignObjectProps = {
width: 350,
height: 300,
x: -200,
y: -50,
};
const treeData = useAppSelector((state) => state.tree);
const [firstTreeData, setFirstTreeData] = useState<TreeData | null>(null);
const restructureTreeData = (node: TreeData): RawNodeDatum => {
const data: RawNodeDatum = {
name: node.firstName,
attributes: {
profile_pic: node.employeeThumbnail,
employee_name: node.firstName + " " + node.lastName,
designation: node.jobRole,
email: node.workEmail,
team: node.team,
managerEmail: node.managerEmail,
subTeam: node.subTeam,
businessUnit: node.businessUnit,
location: node.location,
},
children: [],
};
if (node.children && node.children.length > 0) {
data.children = node.children.map((childNode) =>
restructureTreeData(childNode)
);
}
return data;
};
const renderForeignObjectNode = ({ nodeDatum, foreignObjectProps }: any) => {
return (
<g>
<circle r={12}></circle>
{/* Node data */}
<foreignObject {...foreignObjectProps}>
<OrgData
profile_pic={nodeDatum.attributes.profile_pic}
name={nodeDatum.attributes.employee_name}
designation={nodeDatum.attributes.designation}
email={nodeDatum.attributes.email}
subTeam={nodeDatum.attributes.subTeam}
businessUnit={nodeDatum.attributes.businessUnit}
location={nodeDatum.attributes.location}
team={nodeDatum.attributes.team}
department={nodeDatum.attributes.department}
zoomLevel= {0.3}
selectedEmployee={firstTreeData?.workEmail}
/>
</foreignObject>
</g>
);
};
const treeConfig = {
pathFunc: "step",
translate: { x: 100, y: window.innerHeight/2},
transitionDuration: 1000,
separation: { siblings: 1, nonSiblings: 1 }
};
const transformedTreeData: RawNodeDatum = restructureTreeData(treeData);
const printableRef = useRef(null);
return (
<div>
<Box style={{ height: '100vh'}} ref={printableRef}>
<Tree
data={transformedTreeData}
orientation= "horizontal"
translate={treeConfig.translate}
nodeSize={nodeSize}
separation={treeConfig.separation}
pathFunc="step"
scaleExtent={{ max: 1.0, min: 0.1 }}
zoomable={false}
zoom={0.45}
transitionDuration={treeConfig.transitionDuration}
enableLegacyTransitions={true}
renderCustomNodeElement={(rd3tProps) =>
renderForeignObjectNode({ ...rd3tProps, foreignObjectProps })
}
/>
</Box>
</div>
);
};
export default OrgChart;
Feel like you can add smth like this in the box component
sx={{ maxWidth: '100%', // Set your desired maximum width overflowX: 'auto', // Add horizontal scrollbar when content exceeds max-width }}