On click of a button, I show a chart. When the chart is first instantiated, a ResizeObserver
is set on the parent container of the chart. My application has a collapsible sidebar and when I collapse it, the chart expands to fill up the extra space as expected. However, when I reopen the sidebar, the chart does not shrink back down.
This is the style of the parent container (it is nested within other flex elements so perhaps that is part of the problem?):
<div id={"chartContainer"}
style={{
width: "100%",
height: "100%",
border: "2px solid yellow",
}}
/>
This is the style of the chart:
<div ref={chartRef} style={{ width: "100%", height: "80vh" }}></div>
Relevant component code below, but here is a working example on code sandbox. (If you're on a small screen, you'll have to open the codesandbox in full screen to see all the components. Click "Show Chart" to create the chart, click the "X" in the upper left to collapse the sidebar and the icon in the same place to reopen it.)
export const Chart = () => {
const chartRef = useRef<HTMLDivElement>(null);
useEffect(() => {
let chart: ECharts | undefined;
if (chartRef.current !== null) {
chart = init(chartRef.current, null, { renderer: "svg" });
}
const parentContainer: HTMLDivElement = document.querySelector("#chartContainer");
new ResizeObserver(() => {
chart.resize();
}).observe(parentContainer);
return () => {
chart?.dispose();
};
}, []);
useEffect(() => {
//Update chart
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
chart?.setOption(option);
}
}, [option]);
return <div ref={chartRef} style={{ width: "100%", height: "80vh" }}></div>;
};
I found the answer on a more generalized stackoverflow post.
Essentially, flexboxes enforce a minimum size which is the size of the content. It cannot shrink beyond the size of the content. Adding min-width: 0
to the CSS of the flex container containing the parent container of the chart fixed my problem.
In my example, I am using the Mantine UI Component Library. The flex component I am using that contains the chartContainer
element is called <Stack />
.
Copy of relevant code for posterity: TabContent.tsx
import { useState } from "react";
import { Stack, Center, Button, Title, Box } from "@mantine/core";
import { Chart } from "./Chart";
import styles from "./TabContent.module.css";
export const TabContent = () => {
const [show, setShow] = useState(false);
return (
<>
<Stack className={`${styles.stack} ${styles.leftStack}`}>
<Center>
<Box>
<Title order={1} size="h3">
Visualize Data Menu Area
</Title>
</Box>
</Center>
<Box styles={{ padding: "10px", position: "relative" }}>
<Button onClick={setShow}>Show Chart</Button>
</Box>
</Stack>
<Stack className={`${styles.stack} ${styles.rightStack}`}>
<div
id={"chartContainer"}
style={{
width: "100%",
height: "100%",
border: "2px solid yellow",
// display: "flex",
}}
>
{show && <Chart />}
</div>
</Stack>
</>
);
};
Edit I made to TabContent.modules.css
:
.rightStack {
flex: 1;
min-width: 0;
}
Updated codesandbox.