2

I'm attempting to make a responsive line graph with nivo.

I've recreated my attempt with this MWE:

import React, { useState, useEffect } from "react";
import { ResponsiveLine } from "@nivo/line";
import styled from "styled-components";

const HoursGraphWrapper = styled.div`
  display: grid;
  grid-template-rows: 300px;
  grid-template-columns: 1fr;
  grid-gap: 10px;
`;

const useWindowWidth = () => {
  let width, setWidth;
  if (typeof window !== "undefined") {
    [width, setWidth] = useState(window.innerWidth);
  } else {
    [width, setWidth] = useState(1001);
  }

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    window.addEventListener("resize", handleResize);
    return () => {
      window.removeEventListener("resize", handleResize);
    };
  });

  return width;
};

const TestGraph = () => {
  const width = useWindowWidth();

  return (
    <HoursGraphWrapper>
      <ResponsiveLine
        data={[
          {
            id: "A",
            data: [
              { x: "2019-01-11", y: 11 },
              { x: "2019-01-12", y: 20 },
              { x: "2019-01-13", y: 24 },
              { x: "2019-01-14", y: 25 },
              { x: "2019-01-15", y: 15 },
              { x: "2019-01-16", y: 50 },
              { x: "2019-01-17", y: 30 },
              { x: "2019-01-18", y: 31 }
            ]
          },
          {
            id: "B",
            data: [
              { x: "2019-01-11", y: 30 },
              { x: "2019-01-12", y: 24 },
              { x: "2019-01-13", y: 22 },
              { x: "2019-01-14", y: 15 },
              { x: "2019-01-15", y: 35 },
              { x: "2019-01-16", y: 45 },
              { x: "2019-01-17", y: 20 },
              { x: "2019-01-18", y: 11 }
            ]
          }
        ]}
        colors={{ scheme: "set1" }}
        xScale={{
          type: "time",
          format: "%Y-%m-%d",
          precision: "day"
        }}
        xFormat="time:%Y-%m-%d"
        yScale={{
          type: "linear",
          stacked: false
        }}
        axisLeft={{
          format: value => `${value}hr`,
          legend: "Total Hours",
          legendOffset: -50,
          legendPosition: "middle"
        }}
        axisBottom={{
          format: "%b %d",
          legend: "Date",
          legendOffset: 36,
          legendPosition: "middle",
          tickValues: width < 1000 ? 5 : undefined
        }}
        curve="monotoneX"
        enablePoints={width > 1000}
        pointBorderWidth={1}
        useMesh={true}
        enableSlices={false}
        margin={{ top: 10, right: 20, bottom: 60, left: 80 }}
        animate={true}
      />
    </HoursGraphWrapper>
  );
};

export default TestGraph;

If I make the browser wider - the line graph is responsive as you would expect, filling the space.

The problem I have is if I make the browser narrower the graph does not resize to fill 100% of the browser width as it does when I make it wider. It remains too wide for the new browser width. Interestingly on refresh the graph always occupies 100% of the browser.

How can I make the graph occupy 100% of the browser when making the browser wider and narrower?

BML91
  • 2,952
  • 3
  • 32
  • 54

1 Answers1

7

I have solved this one with thanks to this question and answer on SO: Flex items not shrinking when window gets smaller

The solution is to add a div wrapper around the ResponsiveLine graph with the following style:

min-width: 0;

BML91
  • 2,952
  • 3
  • 32
  • 54
  • 1
    Man, you saved my day hahahaha – Helton Fábio Jun 01 '21 at 02:31
  • Worked for me too. thanks. I also had issues with the height not going back to the original position, min-height didn't fix it, so I used CSS to target the SVG and set the height to the default in my case. – Chris Josh Sep 28 '21 at 12:18