Skip to content

Commit

Permalink
Merge pull request #27 from pyyding/kp-chart-label
Browse files Browse the repository at this point in the history
Chart Label component
  • Loading branch information
ferrucc-io authored May 8, 2024
2 parents bcf675b + 5547380 commit 0c0834e
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 25 deletions.
45 changes: 45 additions & 0 deletions lib/components/ChartLabel/ChartLabelText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { ViewBox } from "recharts/types/util/types";
import React from "react";
import { cx } from "../common/utils.ts";

export type ChartLabelTextProps = {
children: React.ReactNode;
dy?: number;
dx?: number;
viewBox?: ViewBox;
className?: string;
};

export function ChartLabelText({
children,
dy = -5,
dx = 0,
viewBox,
className,
}: ChartLabelTextProps) {
if (!viewBox) {
console.warn("ChartLabelText requires a viewBox prop");
return null;
}

const isCartesianViewBox = "x" in viewBox && "y" in viewBox;

if (!isCartesianViewBox) {
console.warn("ChartLabelText currently only accepts CartesianViewBox");
return null;
}

return (
<text
fontSize="10px"
x={viewBox.x}
y={viewBox.y}
dy={dy}
dx={dx}
stroke="none"
className={cx(className, "fill-purple-500")}
>
{children}
</text>
);
}
4 changes: 4 additions & 0 deletions lib/components/ChartLabel/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export {
Label as ChartLabel,
type LabelProps as ChartLabelProps,
} from "recharts";
5 changes: 5 additions & 0 deletions lib/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,8 @@ export { Dot } from "./components/Dot";
export { defaultDotProps } from "./components/Dot/constants";

export { Legend, type LegendProps } from "./components/Legend";
export { ChartLabel, type ChartLabelProps } from "./components/ChartLabel";
export {
ChartLabelText,
type ChartLabelTextProps,
} from "./components/ChartLabel/ChartLabelText.tsx";
69 changes: 44 additions & 25 deletions src/stories/AreaChart.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
ReferenceLine,
XAxis,
YAxis,
ChartLabel,
ChartLabelText,
} from "../../lib/main.ts";

type Story = StoryObj<typeof AreaChart>;
Expand All @@ -24,10 +26,10 @@ const data = [
{ x: "Mon", y: 0 },
{ x: "Tue", y: 30 },
{ x: "Wed", y: 20 },
{ x: "Thu", y: 35 },
{ x: "Thu", y: 60 },
{ x: "Fri", y: 27 },
{ x: "Sat", y: 40 },
{ x: "Sun", y: 60 },
{ x: "Sun", y: 30 },
];

const meta: Meta<typeof AreaChart> = {
Expand All @@ -45,31 +47,48 @@ export default meta;
export const Default: Story = {
args: {
data,
margin: { top: 20, left: 10, right: 10, bottom: 10 },
},
render: (args) => (
<div>
<AreaChart {...args}>
<Grid {...defaultGridProps} />
<YAxis {...defaultYAxisProps} dataKey="y" />
<XAxis {...defaultXAxisProps} dataKey="x" />
<ReferenceLine {...defaultReferenceLineProps} x="Wed" />
<ChartTooltip
content={({ active, payload, label }) => <DefaultTooltip label={label} active={active} payload={payload} valueFormatter={(p)=> `${p.y} count`} />}
/>
<Area {...defaultAreaProps}
activeDot={
<Dot {...defaultDotProps} onClick={()=>{}} cursor={"pointer"} />
}
dataKey="y" />
<Legend
content={() => (
<div className="text-center">
<div>x – day</div>
<div>y – users</div>
</div>
<AreaChart {...args}>
<Grid {...defaultGridProps} />
<YAxis {...defaultYAxisProps} dataKey="y" />
<XAxis {...defaultXAxisProps} dataKey="x" />
<ChartTooltip
content={({ active, payload, label }) => (
<DefaultTooltip
label={label}
active={active}
payload={payload}
valueFormatter={(p) => `${p.y} count`}
/>
)}
/>
<ReferenceLine
{...defaultReferenceLineProps}
y={data.sort((a, b) => b.y - a.y)[0].y}
>
<ChartLabel
content={({ viewBox }) => (
<ChartLabelText viewBox={viewBox}>All time high</ChartLabelText>
)}
/>
</AreaChart>
</div>
></ChartLabel>
</ReferenceLine>
<Area
{...defaultAreaProps}
activeDot={
<Dot {...defaultDotProps} onClick={() => {}} cursor={"pointer"} />
}
dataKey="y"
/>
<Legend
content={() => (
<div className="text-center">
<div>x – day</div>
<div>y – users</div>
</div>
)}
/>
</AreaChart>
),
};
57 changes: 57 additions & 0 deletions src/tests/components/ChartLabelText.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { render, screen } from "../test-utils.ts";
import { ChartLabelText } from "../../../lib/main.ts";

describe("Component ChartLabelText", () => {
it("should render when correct viewBox is provided", async () => {
render(
<svg>
<ChartLabelText viewBox={{ x: 0, y: 0 }}>test-label</ChartLabelText>,
</svg>,
);
expect(await screen.findByText("test-label")).toBeInTheDocument();
});

it("should not render when no viewBox", () => {
render(
<svg>
<ChartLabelText>test-label</ChartLabelText>
</svg>,
);
expect(screen.queryByText("test-label")).not.toBeInTheDocument();
});

it("should not render when viewBox is PolarViewBox", () => {
render(
<svg>
<ChartLabelText viewBox={{ cx: 0, cy: 0 }}>test-label</ChartLabelText>
</svg>,
);
expect(screen.queryByText("test-label")).not.toBeInTheDocument();
});

it("should render with custom classNames", async () => {
render(
<svg>
<ChartLabelText viewBox={{ x: 0, y: 0 }} className="fill-red-500">
test-label
</ChartLabelText>
</svg>,
);
expect(await screen.findByText("test-label")).toHaveClass("fill-red-500");
});

it("should override default dy and dx", async () => {
render(
<svg>
<ChartLabelText viewBox={{ x: 0, y: 0 }} dy={12} dx={34}>
test-label
</ChartLabelText>
</svg>,
);

const element = await screen.findByText("test-label");

expect(element).toHaveAttribute("dy", "12");
expect(element).toHaveAttribute("dx", "34");
});
});

0 comments on commit 0c0834e

Please sign in to comment.