Hex Core JS
    Preparing search index...

    Module Charts - v0.2.0

    Charts

    Hex Core charts library.

    npm i @hex-insights/charts
    

    Usage

    This component is not a standalone packages, but instead provides useful functionality for the recharts package.

    Because of the way recharts is organized, there is no way to wrap most components. While this seems like a huge drawback, they do have some reasoning for this design. Also, the recharts package is still under development, and is not supported by some huge tech corporation. As a result, if there is some problem with recharts, instead of opening yet another issue, we should try to find the problem and open a PR, possibly even try to become a maintainer.

    A related issue is that inline maps will often fail to render. Instead, predefine the mapped values into a variable and then render as a child.

    A minimal line chart.

    import { LineChart, Line } from "recharts";
    import { defaultLineProps } from "@hex-insights/charts";

    const data = [
    { value: 0 },
    { value: 69 },
    { value: 109 },
    { value: 138 },
    { value: 160 },
    { value: 179 },
    ];

    function App() {
    return (
    <LineChart width={400} height={300} data={data}>
    <Line {...defaultLineProps} dataKey="value" />
    </LineChart>
    );
    }

    Notice that data is sorted according to the order it is given, not based on an x value. So data needs to be sorted ahead of time.

    Another example, this time with axes.

    const data = [
    {
    xAxis: 1,
    yAxis: 100,
    },
    {
    xAxis: 2,
    yAxis: 141,
    },
    {
    xAxis: 3,
    yAxis: 173,
    },
    ];

    function App() {
    return (
    <LineChart width={400} height={300} data={data}>
    <XAxis dataKey="xValue" />
    <YAxis />
    <Line {...defaultLineProps} dataKey="yValue" />
    </LineChart>
    );
    }

    Finally an example with all the bells and whistles we want in a standard line chart. Since the underlying components are almost always svg elements, you can pass standard svg props to most components in recharts. Most commonly these will be fill, stroke, strokeWidth, and strokeDashArray.

    import {
    LineChart,
    Line,
    XAxis,
    YAxis,
    CartesianGrid,
    Tooltip,
    Legend,
    } from "recharts";
    import { defaultLineProps } from "./Modules/Props/Line";

    const data = [...];

    function App() {
    return (
    <LineChart width={400} height={300} data={data}>
    <XAxis dataKey="xValue" />
    <YAxis />
    <CartesianGrid strokeDasharray="3 3" />
    <Tooltip isAnimationActive={false} />
    <Legend />
    <Line
    {...defaultLineProps}
    dataKey="yValue"
    stroke="#aec"
    strokeWidth={3}
    />
    </LineChart>
    );
    }

    As mentioned earlier, when defining multiple child components, special care must be taken. If the keys are computed or otherwise can't be specified ahead of time, we need to use a map. This map cannot directly appear as a child of a chart.

    Here we also see an example of using the useColor hook.

    import { defaultLineProps, useColors } from "@hex-insights/charts";

    const data = [
    { xValue: 1, yValue1: 0, yValue2: 100 },
    { xValue: 2, yValue1: 69, yValue2: 141 },
    { xValue: 3, yValue1: 109, yValue2: 173 },
    { xValue: 4, yValue1: 138, yValue2: 200 },
    { xValue: 5, yValue1: 160, yValue2: 223 },
    { xValue: 6, yValue1: 179, yValue2: 244 },
    ];
    const valueKeys = ["yValue1", "yValue2"];

    function App() {
    const getColor = useColors("pastel1");

    // predefined lines
    const lines = React.useMemo(
    () =>
    valueKeys.map((dataKey, i) => (
    <Line
    {...defaultLineProps}
    key={`${dataKey}-${i}`}
    dataKey={dataKey}
    stroke={getColor(i)}
    strokeWidth={3}
    />
    )),
    [getColor]
    );

    return (
    <LineChart width={400} height={300} data={data}>
    {lines}
    </LineChart>
    );
    }

    Adding Labels is very easy in recharts. However, we also want to make sure labels are visible on dark or bright background colors. For this, we can use the isHexColorLight helper function from the @hex-insights/core package.

    Adding a label is as simple as including the LabelList component.

    function App() {
    const getColor = useColor("paired");

    const bars = React.useMemo(
    () =>
    ["value1", "value2"].map((dataKey, i) => (
    <Bar
    {...defaultStackedBarProps}
    dataKey={dataKey}
    fill={getColor(i)}
    >
    <LabelList
    dataKey={dataKey}
    fill={isHexColorLight(getColor(i)) ? "black" : "white"}
    />
    </Bar>
    )),
    [getColor]
    );

    return (
    <BarChart width={400} height={300} data={data}>
    {bars}
    </BarChart>
    );
    }

    There is one Unfortunate missing feature: hiding labels if they are too small. However this could be circumvented by adding a custom label.

    Pie charts works slightly differently from any other chart type. Instead of passing data to the PieChart component and then picking out the key with the dataKey prop on Pie, both data and dataKey are passed to the Pie component.

    <PieChart width={400} height={300}>
    <Pie data={data} dataKey="value1" fill="#f00" label />
    </PieChart>

    In order to have distinct colors per slice, we need to use the Cell component.

    function App() {
    const getColor = useColor("tableau10");

    const cells = React.useMemo(
    () => data.map((_, i) => <Cell fill={getColor(i)} />),
    [getColor]
    );

    return (
    <PieChart width={400} height={300}>
    <Pie {...defaultPieProps} data={data} dataKey="value">
    {cells}
    </Pie>
    </PieChart>
    );
    }

    We can make "donut" charts by adjusting the innerRadius of a pie chart.

    Here is an example of a more stylized "donut" pie chart with some other features as well.

    <PieChart width={400} height={300}>
    <Pie
    {...defaultPieProps}
    data={data}
    startAngle={90} // start at the top
    endAngle={450} // end after going 360 degrees
    paddingAngle={2}
    cornerRadius={5}
    innerRadius="50%"
    dataKey="value"
    >
    {cells}
    </Pie>
    </PieChart>

    One extremely nice feature that "just works" are brushes.

    <BarChart data={data}>
    <Brush dataKey="xValue" />
    {bars}
    </BarChart>

    recharts handles resizing nicely out of the box. For example, to make a chart with a fixed aspect ratio but dynamic width, we just need to use the ResponsiveContainer component.

    <ResponsiveContainer width="100%" aspect={16/9}>
    <BarChart data={data}>
    {bars}
    </BarChart>
    </ResponsiveContainer>

    There are lots of other smaller components which can be seen on the recharts api page. Unfortunately the exact api is slightly out of date, but the components themselves don't seem to be.

    English API docs here.

    You can even mix in svg features to define e.g. gradients.

    For example, we can build a simple inline stock chart.

    const data = [...Array(50)].map((_, k) => ({
    price: Math.floor(100 * Math.sin(0.18 * k) + 25 * Math.sin(123 * k)),
    }));

    function App() {
    const gradientOffset = React.useMemo(() => {
    const dataMax = Math.max(...data.map(({ price }) => price));
    const dataMin = Math.min(...data.map(({ price }) => price));

    if (dataMax <= 0) {
    return 0;
    }
    if (dataMin >= 0) {
    return 1;
    }

    return dataMax / (dataMax - dataMin);
    }, []);

    return (
    <ResponsiveContainer width={100} aspect={2}>
    <AreaChart
    margin={{
    left: 0,
    right: 0,
    top: 0,
    bottom: 0,
    }}
    data={data}
    >
    <defs>
    <linearGradient id="fillColor" x1="0" y1="0" x2="0" y2="1">
    <stop offset={0} stopColor="green" stopOpacity={1} />
    <stop
    offset={gradientOffset}
    stopColor="#fff"
    stopOpacity={0}
    />
    <stop offset={1} stopColor="red" stopOpacity={1} />
    </linearGradient>
    <linearGradient
    id="strokeColor"
    x1="0"
    y1="0"
    x2="0"
    y2="1"
    >
    <stop
    offset={gradientOffset}
    stopColor="green"
    stopOpacity={1}
    />
    <stop
    offset={gradientOffset}
    stopColor="red"
    stopOpacity={1}
    />
    </linearGradient>
    </defs>
    <Area
    type="monotone"
    dataKey="price"
    fill="url(#fillColor)"
    stroke="url(#strokeColor)"
    strokeWidth={1}
    dot={false}
    />
    <ReferenceLine
    y={0}
    stroke={gradientOffset < 0.5 ? "red" : "green"}
    strokeDasharray="3 2"
    />
    </AreaChart>
    </ResponsiveContainer>
    );
    }

    Type Aliases

    AreaProps
    BarProps
    ColorSchemeName
    LineProps
    PieProps

    Variables

    categoricalColorSchemes
    defaultAreaProps
    defaultBarProps
    defaultLineProps
    defaultPieProps
    defaultStackedBarProps

    Functions

    useColors
    useOpacity