plouc / nivo

nivo provides a rich set of dataviz components, built on top of the awesome d3 and React libraries
https://nivo.rocks
MIT License
13.08k stars 1.02k forks source link

0.83.0 no longer accepts react components for axis formatting #2399

Closed mattoni closed 1 year ago

mattoni commented 1 year ago

Thanks for using nivo

Before creating an issue...

Are you asking a question?

Please don't file GitHub issues to ask questions. Try to use the discord channel first: https://discord.gg/n7Ft74f.

Describe/explain the bug axisLeft etc no longer is accepting a react component for custom formatting.

To Reproduce Please include a test case that demonstrates the issue you're reporting on a platform like codesandbox, I already have several existing examples on codesandbox, you can fork one of them depending on the component you're working on: https://codesandbox.io/u/plouc/sandboxes. This is very critical to maintainers in order to help us see the issue you're seeing.

https://codesandbox.io/s/nivo-line-chart-bottom-tick-values-forked-9vdmck?file=/src/index.js

Steps to reproduce the behavior:

  1. In the above code sandbox, observe the axis renders
  2. Upgrade to 0.83.0
  3. Notice the axis is now [object Object]

Expected behavior I expect this functionality to not have broken, or to be documented somewhere that it no longer accepts react components.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

Additional context Formatting these has been a very precise process for my app. Without custom components, there should be equal ability to style things custom. For example one of ours looks like this:

  axisBottom={{
                format: (v) => {
                    const d = format(v, "MMM d");
                    const t = format(v, TimeFormats["standard"]);

                    const showDate = shouldShowDate(option);
                    return (
                        <>
                            {showDate ? (
                                <tspan
                                    fontSize={12}
                                    fill={
                                        isDark
                                            ? brandColors["cycle-gray"].light
                                            : undefined
                                    }
                                >
                                    {d}
                                </tspan>
                            ) : null}
                            <tspan
                                dy={showDate ? "12px" : undefined}
                                dx={showDate ? "-38px" : undefined}
                                fontSize={11}
                                fill={
                                    isDark
                                        ? brandColors["cycle-gray"].light
                                        : undefined
                                }
                            >
                                {t}
                            </tspan>
                        </>
                    );

and I'm pretty happy with how it turned out, redoing the dozens of charts across the app would be a nightmare.

ollwenjones commented 1 year ago

I think you want the renderTick prop, now, not the format one, for custom tick components

export interface AxisProps<Value extends ScaleValue = any> {
    ticksPosition?: 'before' | 'after';
    tickValues?: TicksSpec<Value>;
    tickSize?: number;
    tickPadding?: number;
    tickRotation?: number;
    format?: string | ValueFormatter<Value>; // <- just formatting the string, not JSX
    renderTick?: (props: AxisTickProps<Value>) => JSX.Element; // <- this guy for custom components
    legend?: React.ReactNode;
    legendPosition?: AxisLegendPosition;
    legendOffset?: number;
    ariaHidden?: boolean;
}
mattoni commented 1 year ago

Thank you, though it seems to work a bit differently. I didn't see anything in the changelog that would indicate this happened.

plouc commented 1 year ago

The fact that components were accepted in the past was somehow accidental, the proper way to override the component is to use renderTick. Sorry about the changelog.

plouc commented 1 year ago

The reason for the change was to clearly dissociate formatting and rendering, as it behaves differently depending on the implementation (SVG vs canvas).