shadcn-ui / ui

Beautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source.
https://ui.shadcn.com
MIT License
74.56k stars 4.63k forks source link

[feat]: Be able to set have minWidth and overflowing behavior when width is small. #4198

Closed spencerrazor closed 3 months ago

spencerrazor commented 4 months ago

Feature description

All the examples present in the docs squish all the data points into the available width. Sometimes the number of data points are far too great to even be readable on the chart, thus warranting being the ability to scroll.

I hacked a way to make the the chart horizontally scrollable based off the minWidth property of the ResponsiveContainer primitive. I had to wrap this primitive in a div with className "overflow-x-auto" to allow scroll. I also used a useEffect to set the scrollPosition to the center, because the legend was being scrolled as well and I wanted it initially visible.

Ideally, I want the legend to be fixed and only the actual chart (the data) to be scrolled.

I think there should be an easier way to handle this kind of responsiveness. Maybe there is a simpler way than what I did. Please comment if there a better way of doing this!

const ChartContainer = React.forwardRef<
  HTMLDivElement,
  React.ComponentProps<"div"> & {
    config: ChartConfig
    children: React.ComponentProps<
      typeof RechartsPrimitive.ResponsiveContainer
    >["children"]
  }
>(({ id, className, children, config, ...props }, ref) => {
  const uniqueId = React.useId()
  const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`

  React.useEffect(() => {
    const scrollContainer = document.getElementById('scroll-container')
    const content = document.getElementById('content')
    const middlePosition = (content.offsetWidth - scrollContainer.clientWidth) / 2;

    scrollContainer.scrollLeft = middlePosition;
  }, [])

  return (
    <ChartContext.Provider value={{ config }}>
      <div
        data-chart={chartId}
        ref={ref}
        className={cn(
          "w-full overflow-x-auto flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line-line]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
          className
        )}
        {...props}
      >
        <ChartStyle id={chartId} config={config} />
        <div className="overflow-x-auto" id="scroll-container">
        <RechartsPrimitive.ResponsiveContainer minWidth="600px" id="content">
          {children}
        </RechartsPrimitive.ResponsiveContainer>
        </div>
      </div>
    </ChartContext.Provider>
  )
})
ChartContainer.displayName = "Chart"

Affected component/components

Chart

Additional Context

No response

Before submitting

shadcn commented 3 months ago

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.